mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 07:10:07 +00:00
Merge branch 'development' into clone
This commit is contained in:
commit
bfc6563405
@ -12,7 +12,7 @@ env:
|
||||
|
||||
# Make sure CMake is installed
|
||||
install:
|
||||
- sudo apt-get install cmake
|
||||
- sudo apt-get install cmake valgrind
|
||||
|
||||
# Run the Build script
|
||||
script:
|
||||
@ -24,6 +24,7 @@ script:
|
||||
# Run Tests
|
||||
after_script:
|
||||
- ctest -V .
|
||||
- if [ -f ./libgit2_clar ]; then valgrind --leak-check=full --show-reachable=yes ./libgit2_clar; else echo "Skipping valgrind"; fi
|
||||
|
||||
# Only watch the development branch
|
||||
branches:
|
||||
|
@ -21,13 +21,30 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_V
|
||||
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
|
||||
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
|
||||
|
||||
IF (AMIGA)
|
||||
# Default AmigaOS to use the PowerPC SHA1
|
||||
SET(SHA1_TYPE "ppc")
|
||||
ENDIF()
|
||||
|
||||
# Find required dependencies
|
||||
INCLUDE_DIRECTORIES(src include deps/http-parser)
|
||||
|
||||
FILE(GLOB SRC_HTTP deps/http-parser/*.c)
|
||||
|
||||
# Specify sha1 implementation
|
||||
IF (SHA1_TYPE STREQUAL "ppc")
|
||||
ADD_DEFINITIONS(-DPPC_SHA1)
|
||||
FILE(GLOB SRC_SHA1 src/ppc/*.c src/ppc/*.S)
|
||||
ELSE ()
|
||||
SET (SRC_SHA1)
|
||||
ENDIF()
|
||||
|
||||
IF (NOT WIN32)
|
||||
FIND_PACKAGE(ZLIB)
|
||||
IF (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
|
||||
INCLUDE_DIRECTORIES(deps/regex)
|
||||
SET(SRC_REGEX deps/regex/regex.c)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
# Windows doesn't understand POSIX regex on its own
|
||||
INCLUDE_DIRECTORIES(deps/regex)
|
||||
@ -45,7 +62,7 @@ ENDIF()
|
||||
|
||||
# Installation paths
|
||||
SET(INSTALL_BIN bin CACHE PATH "Where to install binaries to.")
|
||||
SET(INSTALL_LIB lib CACHE PATH "Where to install libraries to.")
|
||||
SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.")
|
||||
SET(INSTALL_INC include CACHE PATH "Where to install headers to.")
|
||||
|
||||
# Build options
|
||||
@ -115,12 +132,15 @@ IF (WIN32 AND NOT CYGWIN)
|
||||
FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/win32/*.c src/compat/*.c)
|
||||
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/unix/*.c src/compat/*.c)
|
||||
ELSEIF (AMIGA)
|
||||
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R)
|
||||
FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/amiga/*.c src/compat/*.c)
|
||||
ELSE()
|
||||
FILE(GLOB SRC src/*.c src/transports/*.c src/xdiff/*.c src/unix/*.c)
|
||||
ENDIF ()
|
||||
|
||||
# Compile and link libgit2
|
||||
ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${WIN_RC})
|
||||
ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
|
||||
|
||||
IF (WIN32)
|
||||
TARGET_LINK_LIBRARIES(git2 ws2_32)
|
||||
@ -139,13 +159,18 @@ IF (MSVC)
|
||||
SET_SOURCE_FILES_PROPERTIES(src/win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
|
||||
ENDIF ()
|
||||
|
||||
# Backward compatibility with INSTALL_LIB variable
|
||||
if (INSTALL_LIB)
|
||||
set(LIB_INSTALL_DIR "${INSTALL_LIB}")
|
||||
ENDIF()
|
||||
|
||||
# Install
|
||||
INSTALL(TARGETS git2
|
||||
RUNTIME DESTINATION ${INSTALL_BIN}
|
||||
LIBRARY DESTINATION ${INSTALL_LIB}
|
||||
ARCHIVE DESTINATION ${INSTALL_LIB}
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${INSTALL_LIB}/pkgconfig )
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
|
||||
INSTALL(DIRECTORY include/git2 DESTINATION ${INSTALL_INC} )
|
||||
INSTALL(FILES include/git2.h DESTINATION ${INSTALL_INC} )
|
||||
|
||||
|
@ -67,7 +67,7 @@ For more advanced use or questions about CMake please read <http://www.cmake.org
|
||||
The following CMake variables are declared:
|
||||
|
||||
- `INSTALL_BIN`: Where to install binaries to.
|
||||
- `INSTALL_LIB`: Where to install libraries to.
|
||||
- `LIB_INSTALL_DIR`: Where to install libraries to.
|
||||
- `INSTALL_INC`: Where to install headers to.
|
||||
- `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to ON)
|
||||
- `BUILD_CLAR`: Build [Clar](https://github.com/tanoku/clar)-based test suite (defaults to ON)
|
||||
@ -89,7 +89,7 @@ Here are the bindings to libgit2 that are currently available:
|
||||
* Go
|
||||
* go-git <https://github.com/str1ngs/go-git>
|
||||
* GObject
|
||||
* libgit2-glib <http://git.gnome.org/browse/libgit2-glib>
|
||||
* libgit2-glib <https://live.gnome.org/Libgit2-glib>
|
||||
* Haskell
|
||||
* hgit2 <https://github.com/norm2782/hgit2>
|
||||
* Lua
|
||||
|
11
examples/README.md
Normal file
11
examples/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
libgit2 examples
|
||||
================
|
||||
|
||||
These examples are meant as thin, easy-to-read snippets for Docurium
|
||||
(https://github.com/github/docurium) rather than full-blown
|
||||
implementations of Git commands. They are not vetted as carefully
|
||||
for bugs, error handling, or cross-platform compatibility as the
|
||||
rest of the code in libgit2, so copy with some caution.
|
||||
|
||||
For HTML versions, check "Examples" at http://libgit2.github.com/libgit2
|
||||
|
@ -2,7 +2,7 @@ default: all
|
||||
|
||||
CC = gcc
|
||||
CFLAGS += -g
|
||||
CFLAGS += -I../../include -L../../ -lgit2 -lpthread
|
||||
CFLAGS += -I../../include -L../../build -L../.. -lgit2 -lpthread
|
||||
|
||||
OBJECTS = \
|
||||
git2.o \
|
||||
|
@ -91,6 +91,7 @@ int fetch(git_repository *repo, int argc, char **argv)
|
||||
usleep(10000);
|
||||
printf("\rReceived %d/%d objects in %d bytes", stats.processed, stats.total, bytes);
|
||||
} while (!data.finished);
|
||||
|
||||
printf("\rReceived %d/%d objects in %d bytes\n", stats.processed, stats.total, bytes);
|
||||
|
||||
// Disconnect the underlying connection to prevent from idling.
|
||||
|
@ -25,7 +25,7 @@ int index_pack(git_repository *repo, int argc, char **argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (git_indexer_stream_new(&idx, ".git") < 0) {
|
||||
if (git_indexer_stream_new(&idx, ".") < 0) {
|
||||
puts("bad idx");
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "git2/remote.h"
|
||||
#include "git2/clone.h"
|
||||
|
||||
#include "git2/attr.h"
|
||||
#include "git2/branch.h"
|
||||
#include "git2/refspec.h"
|
||||
#include "git2/net.h"
|
||||
#include "git2/status.h"
|
||||
|
@ -30,7 +30,7 @@ GIT_BEGIN_DECL
|
||||
* Then for file `xyz.c` looking up attribute "foo" gives a value for
|
||||
* which `GIT_ATTR_TRUE(value)` is true.
|
||||
*/
|
||||
#define GIT_ATTR_TRUE(attr) ((attr) == git_attr__true)
|
||||
#define GIT_ATTR_TRUE(attr) ((attr) == git_l_attr__true)
|
||||
|
||||
/**
|
||||
* GIT_ATTR_FALSE checks if an attribute is set off. In core git
|
||||
@ -44,7 +44,7 @@ GIT_BEGIN_DECL
|
||||
* Then for file `zyx.h` looking up attribute "foo" gives a value for
|
||||
* which `GIT_ATTR_FALSE(value)` is true.
|
||||
*/
|
||||
#define GIT_ATTR_FALSE(attr) ((attr) == git_attr__false)
|
||||
#define GIT_ATTR_FALSE(attr) ((attr) == git_l_attr__false)
|
||||
|
||||
/**
|
||||
* GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified. This
|
||||
@ -62,7 +62,7 @@ GIT_BEGIN_DECL
|
||||
* file `onefile.rb` or looking up "bar" on any file will all give
|
||||
* `GIT_ATTR_UNSPECIFIED(value)` of true.
|
||||
*/
|
||||
#define GIT_ATTR_UNSPECIFIED(attr) (!(attr) || (attr) == git_attr__unset)
|
||||
#define GIT_ATTR_UNSPECIFIED(attr) (!(attr) || (attr) == git_l_attr__unset)
|
||||
|
||||
/**
|
||||
* GIT_ATTR_HAS_VALUE checks if an attribute is set to a value (as
|
||||
@ -75,12 +75,12 @@ GIT_BEGIN_DECL
|
||||
* string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true.
|
||||
*/
|
||||
#define GIT_ATTR_HAS_VALUE(attr) \
|
||||
((attr) && (attr) != git_attr__unset && \
|
||||
(attr) != git_attr__true && (attr) != git_attr__false)
|
||||
((attr) && (attr) != git_l_attr__unset && \
|
||||
(attr) != git_l_attr__true && (attr) != git_attr__false)
|
||||
|
||||
GIT_EXTERN(const char *) git_attr__true;
|
||||
GIT_EXTERN(const char *) git_attr__false;
|
||||
GIT_EXTERN(const char *) git_attr__unset;
|
||||
GIT_EXTERN(const char *) git_l_attr__true;
|
||||
GIT_EXTERN(const char *) git_l_attr__false;
|
||||
GIT_EXTERN(const char *) git_l_attr__unset;
|
||||
|
||||
/**
|
||||
* Check attribute flags: Reading values from index and working directory.
|
||||
|
@ -72,15 +72,7 @@ GIT_EXTERN(int) git_branch_delete(
|
||||
git_branch_t branch_type);
|
||||
|
||||
/**
|
||||
* Fill a list with all the branches in the Repository
|
||||
*
|
||||
* The string array will be filled with the names of the
|
||||
* matching branches; these values are owned by the user and
|
||||
* should be free'd manually when no longer needed, using
|
||||
* `git_strarray_free`.
|
||||
*
|
||||
* @param branch_names Pointer to a git_strarray structure
|
||||
* where the branch names will be stored.
|
||||
* Loop over all the branches and issue a callback for each one.
|
||||
*
|
||||
* @param repo Repository where to find the branches.
|
||||
*
|
||||
@ -88,12 +80,21 @@ GIT_EXTERN(int) git_branch_delete(
|
||||
* listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE
|
||||
* or a combination of the two.
|
||||
*
|
||||
* @param branch_cb Callback to invoke per found branch.
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 or an error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_branch_list(
|
||||
git_strarray *branch_names,
|
||||
GIT_EXTERN(int) git_branch_foreach(
|
||||
git_repository *repo,
|
||||
unsigned int list_flags);
|
||||
unsigned int list_flags,
|
||||
int (*branch_cb)(
|
||||
const char *branch_name,
|
||||
git_branch_t branch_type,
|
||||
void *payload),
|
||||
void *payload
|
||||
);
|
||||
|
||||
/**
|
||||
* Move/rename an existing branch reference.
|
||||
|
@ -178,6 +178,25 @@ GIT_EXTERN(int) git_commit_parent(git_commit **parent, git_commit *commit, unsig
|
||||
*/
|
||||
GIT_EXTERN(const git_oid *) git_commit_parent_oid(git_commit *commit, unsigned int n);
|
||||
|
||||
/**
|
||||
* Get the commit object that is the <n>th generation ancestor
|
||||
* of the named commit object, following only the first parents.
|
||||
* The returned commit has to be freed by the caller.
|
||||
*
|
||||
* Passing `0` as the generation number returns another instance of the
|
||||
* base commit itself.
|
||||
*
|
||||
* @param ancestor Pointer where to store the ancestor commit
|
||||
* @param commit a previously loaded commit.
|
||||
* @param n the requested generation
|
||||
* @return 0 on success; GIT_ENOTFOUND if no matching ancestor exists
|
||||
* or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_commit_nth_gen_ancestor(
|
||||
git_commit **ancestor,
|
||||
const git_commit *commit,
|
||||
unsigned int n);
|
||||
|
||||
/**
|
||||
* Create a new commit in the repository using `git_object`
|
||||
* instances as parameters.
|
||||
|
@ -55,6 +55,10 @@
|
||||
#define GIT_WIN32 1
|
||||
#endif
|
||||
|
||||
#ifdef __amigaos4__
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file git2/common.h
|
||||
* @brief Git common platform definitions
|
||||
|
@ -33,7 +33,7 @@ struct git_config_file {
|
||||
int (*set)(struct git_config_file *, const char *key, const char *value);
|
||||
int (*set_multivar)(git_config_file *cfg, const char *name, const char *regexp, const char *value);
|
||||
int (*del)(struct git_config_file *, const char *key);
|
||||
int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data);
|
||||
int (*foreach)(struct git_config_file *, const char *, int (*fn)(const char *, const char *, void *), void *data);
|
||||
void (*free)(struct git_config_file *);
|
||||
};
|
||||
|
||||
@ -314,6 +314,24 @@ GIT_EXTERN(int) git_config_foreach(
|
||||
int (*callback)(const char *var_name, const char *value, void *payload),
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Perform an operation on each config variable matching a regular expression.
|
||||
*
|
||||
* This behaviors like `git_config_foreach` with an additional filter of a
|
||||
* regular expression that filters which config keys are passed to the
|
||||
* callback.
|
||||
*
|
||||
* @param cfg where to get the variables from
|
||||
* @param regexp regular expression to match against config names
|
||||
* @param callback the function to call on each variable
|
||||
* @param payload the data to pass to the callback
|
||||
* @return 0 or the return value of the callback which didn't return 0
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_foreach_match(
|
||||
git_config *cfg,
|
||||
const char *regexp,
|
||||
int (*callback)(const char *var_name, const char *value, void *payload),
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Query the value of a config variable and return it mapped to
|
||||
|
@ -60,7 +60,7 @@ enum {
|
||||
typedef struct {
|
||||
uint32_t flags; /**< defaults to GIT_DIFF_NORMAL */
|
||||
uint16_t context_lines; /**< defaults to 3 */
|
||||
uint16_t interhunk_lines; /**< defaults to 3 */
|
||||
uint16_t interhunk_lines; /**< defaults to 0 */
|
||||
char *old_prefix; /**< defaults to "a" */
|
||||
char *new_prefix; /**< defaults to "b" */
|
||||
git_strarray pathspec; /**< defaults to show all paths */
|
||||
|
@ -17,43 +17,6 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
#ifdef GIT_OLD_ERRORS
|
||||
enum {
|
||||
GIT_SUCCESS = 0,
|
||||
GIT_ENOTOID = -2,
|
||||
GIT_ENOTFOUND = -3,
|
||||
GIT_ENOMEM = -4,
|
||||
GIT_EOSERR = -5,
|
||||
GIT_EOBJTYPE = -6,
|
||||
GIT_ENOTAREPO = -7,
|
||||
GIT_EINVALIDTYPE = -8,
|
||||
GIT_EMISSINGOBJDATA = -9,
|
||||
GIT_EPACKCORRUPTED = -10,
|
||||
GIT_EFLOCKFAIL = -11,
|
||||
GIT_EZLIB = -12,
|
||||
GIT_EBUSY = -13,
|
||||
GIT_EBAREINDEX = -14,
|
||||
GIT_EINVALIDREFNAME = -15,
|
||||
GIT_EREFCORRUPTED = -16,
|
||||
GIT_ETOONESTEDSYMREF = -17,
|
||||
GIT_EPACKEDREFSCORRUPTED = -18,
|
||||
GIT_EINVALIDPATH = -19,
|
||||
GIT_EREVWALKOVER = -20,
|
||||
GIT_EINVALIDREFSTATE = -21,
|
||||
GIT_ENOTIMPLEMENTED = -22,
|
||||
GIT_EEXISTS = -23,
|
||||
GIT_EOVERFLOW = -24,
|
||||
GIT_ENOTNUM = -25,
|
||||
GIT_ESTREAM = -26,
|
||||
GIT_EINVALIDARGS = -27,
|
||||
GIT_EOBJCORRUPTED = -28,
|
||||
GIT_EAMBIGUOUS = -29,
|
||||
GIT_EPASSTHROUGH = -30,
|
||||
GIT_ENOMATCH = -31,
|
||||
GIT_ESHORTBUFFER = -32,
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Generic return codes */
|
||||
enum {
|
||||
GIT_OK = 0,
|
||||
@ -72,6 +35,7 @@ typedef struct {
|
||||
int klass;
|
||||
} git_error;
|
||||
|
||||
/** Error classes */
|
||||
typedef enum {
|
||||
GITERR_NOMEMORY,
|
||||
GITERR_OS,
|
||||
|
@ -29,9 +29,9 @@ typedef struct git_indexer_stream git_indexer_stream;
|
||||
* Create a new streaming indexer instance
|
||||
*
|
||||
* @param out where to store the indexer instance
|
||||
* @param path to the gitdir (metadata directory)
|
||||
* @param path to the directory where the packfile should be stored
|
||||
*/
|
||||
GIT_EXTERN(int) git_indexer_stream_new(git_indexer_stream **out, const char *gitdir);
|
||||
GIT_EXTERN(int) git_indexer_stream_new(git_indexer_stream **out, const char *path);
|
||||
|
||||
/**
|
||||
* Add data to the indexer
|
||||
|
@ -172,6 +172,20 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *d
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
|
||||
|
||||
/**
|
||||
* List all objects available in the database
|
||||
*
|
||||
* The callback will be called for each object available in the
|
||||
* database. Note that the objects are likely to be returned in the
|
||||
* index order, which would make accessing the objects in that order
|
||||
* inefficient.
|
||||
*
|
||||
* @param db database to use
|
||||
* @param cb the callback to call for each object
|
||||
* @param data data to pass to the callback
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data);
|
||||
|
||||
/**
|
||||
* Write an object directly into the ODB
|
||||
*
|
||||
|
@ -71,6 +71,12 @@ struct git_odb_backend {
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
int (*foreach)(
|
||||
struct git_odb_backend *,
|
||||
int (*cb)(git_oid *oid, void *data),
|
||||
void *data
|
||||
);
|
||||
|
||||
void (* free)(struct git_odb_backend *);
|
||||
};
|
||||
|
||||
|
@ -53,6 +53,8 @@ GIT_EXTERN(int) git_reflog_write(git_reference *ref, const git_oid *oid_old, con
|
||||
/**
|
||||
* Rename the reflog for the given reference
|
||||
*
|
||||
* The reflog to be renamed is expected to already exist
|
||||
*
|
||||
* @param ref the reference
|
||||
* @param new_name the new name of the reference
|
||||
* @return 0 or an error code
|
||||
|
@ -258,7 +258,6 @@ GIT_EXTERN(int) git_reference_packall(git_repository *repo);
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, unsigned int list_flags);
|
||||
|
||||
|
||||
/**
|
||||
* Perform an operation on each reference in the repository
|
||||
*
|
||||
@ -324,6 +323,67 @@ GIT_EXTERN(void) git_reference_free(git_reference *ref);
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2);
|
||||
|
||||
/**
|
||||
* Loop over all the references and issue a callback for each one
|
||||
* which name matches the given glob pattern.
|
||||
*
|
||||
* The processed references may be filtered by type, or using
|
||||
* a bitwise OR of several types. Use the magic value
|
||||
* `GIT_REF_LISTALL` to obtain all references, including
|
||||
* packed ones.
|
||||
*
|
||||
* @param repo Repository where to find the references.
|
||||
*
|
||||
* @param list_flags Filtering flags for the reference
|
||||
* listing.
|
||||
*
|
||||
* @param callback Callback to invoke per found reference.
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 or an error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_foreach_glob(
|
||||
git_repository *repo,
|
||||
const char *glob,
|
||||
unsigned int list_flags,
|
||||
int (*callback)(
|
||||
const char *reference_name,
|
||||
void *payload),
|
||||
void *payload
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if a reflog exists for the specified reference.
|
||||
*
|
||||
* @param ref A git reference
|
||||
*
|
||||
* @return 0 when no reflog can be found, 1 when it exists;
|
||||
* otherwise an error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_has_log(git_reference *ref);
|
||||
|
||||
|
||||
/**
|
||||
* Return the reference supporting the remote tracking branch,
|
||||
* given a reference branch.
|
||||
*
|
||||
* The input reference has to be located in the `refs/heads`
|
||||
* namespace.
|
||||
*
|
||||
* @param tracking_ref Pointer where to store the retrieved
|
||||
* reference.
|
||||
*
|
||||
* @param branch_ref A git local branch reference.
|
||||
*
|
||||
* @return 0 on success; GIT_ENOTFOUND when no remote tracking
|
||||
* reference exists, otherwise an error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_remote_tracking_from_branch(
|
||||
git_reference **tracking_ref,
|
||||
git_reference *branch_ref
|
||||
);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -194,9 +194,12 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param workdir The path to a working directory
|
||||
* @param update_gitlink Create/update gitlink in workdir and set config
|
||||
* "core.worktree" (if workdir is not the parent of the .git directory)
|
||||
* @return 0, or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_set_workdir(git_repository *repo, const char *workdir);
|
||||
GIT_EXTERN(int) git_repository_set_workdir(
|
||||
git_repository *repo, const char *workdir, int update_gitlink);
|
||||
|
||||
/**
|
||||
* Check if a repository is bare
|
||||
|
@ -107,7 +107,7 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *oid);
|
||||
* The OIDs pointed to by the references that match the given glob
|
||||
* pattern will be pushed to the revision walker.
|
||||
*
|
||||
* A leading 'refs/' is implied it not present as well as a trailing
|
||||
* A leading 'refs/' is implied if not present as well as a trailing
|
||||
* '/ *' if the glob lacks '?', '*' or '['.
|
||||
*
|
||||
* @param walk the walker being used for the traversal
|
||||
@ -146,7 +146,7 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *oid);
|
||||
* pattern and their ancestors will be hidden from the output on the
|
||||
* revision walk.
|
||||
*
|
||||
* A leading 'refs/' is implied it not present as well as a trailing
|
||||
* A leading 'refs/' is implied if not present as well as a trailing
|
||||
* '/ *' if the glob lacks '?', '*' or '['.
|
||||
*
|
||||
* @param walk the walker being used for the traversal
|
||||
|
@ -23,6 +23,9 @@ GIT_BEGIN_DECL
|
||||
* Create a new action signature. The signature must be freed
|
||||
* manually or using git_signature_free
|
||||
*
|
||||
* Note: angle brackets ('<' and '>') characters are not allowed
|
||||
* to be used in either the `name` or the `email` parameter.
|
||||
*
|
||||
* @param sig_out new signature, in case of error NULL
|
||||
* @param name name of the person
|
||||
* @param email email of the person
|
||||
|
@ -46,7 +46,11 @@ GIT_INLINE(int) git_tree_lookup(git_tree **tree, git_repository *repo, const git
|
||||
* @param len the length of the short identifier
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, const git_oid *id, unsigned int len)
|
||||
GIT_INLINE(int) git_tree_lookup_prefix(
|
||||
git_tree **tree,
|
||||
git_repository *repo,
|
||||
const git_oid *id,
|
||||
unsigned int len)
|
||||
{
|
||||
return git_object_lookup_prefix((git_object **)tree, repo, id, len, GIT_OBJ_TREE);
|
||||
}
|
||||
@ -62,12 +66,33 @@ GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, co
|
||||
*
|
||||
* @param tree the tree to close
|
||||
*/
|
||||
|
||||
GIT_INLINE(void) git_tree_free(git_tree *tree)
|
||||
{
|
||||
git_object_free((git_object *) tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a tree entry
|
||||
*
|
||||
* IMPORTANT: This function is only needed for tree
|
||||
* entries owned by the user, such as the ones returned
|
||||
* by `git_tree_entry_dup`.
|
||||
*
|
||||
* @param entry The entry to free
|
||||
*/
|
||||
GIT_EXTERN(void) git_tree_entry_free(git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Duplicate a tree entry
|
||||
*
|
||||
* Create a copy of a tree entry. The returned copy is owned
|
||||
* by the user, and must be freed manually with
|
||||
* `git_tree_entry_free`.
|
||||
*
|
||||
* @param entry A tree entry to duplicate
|
||||
* @return a copy of the original entry
|
||||
*/
|
||||
GIT_EXTERN(git_tree_entry *) git_tree_entry_dup(const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Get the id of a tree.
|
||||
@ -143,7 +168,10 @@ GIT_EXTERN(git_otype) git_tree_entry_type(const git_tree_entry *entry);
|
||||
* @param entry a tree entry
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_tree_entry_to_object(git_object **object_out, git_repository *repo, const git_tree_entry *entry);
|
||||
GIT_EXTERN(int) git_tree_entry_to_object(
|
||||
git_object **object_out,
|
||||
git_repository *repo,
|
||||
const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Write a tree to the ODB from the index file
|
||||
@ -231,7 +259,12 @@ GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(git_treebuilder *bld, con
|
||||
* @param attributes Folder attributes of the entry
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes);
|
||||
GIT_EXTERN(int) git_treebuilder_insert(
|
||||
const git_tree_entry **entry_out,
|
||||
git_treebuilder *bld,
|
||||
const char *filename,
|
||||
const git_oid *id,
|
||||
unsigned int attributes);
|
||||
|
||||
/**
|
||||
* Remove an entry from the builder by its filename
|
||||
@ -252,7 +285,10 @@ GIT_EXTERN(int) git_treebuilder_remove(git_treebuilder *bld, const char *filenam
|
||||
* @param bld Tree builder
|
||||
* @param filter Callback to filter entries
|
||||
*/
|
||||
GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload);
|
||||
GIT_EXTERN(void) git_treebuilder_filter(
|
||||
git_treebuilder *bld,
|
||||
int (*filter)(const git_tree_entry *, void *),
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Write the contents of the tree builder as a tree object
|
||||
@ -269,21 +305,24 @@ GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(cons
|
||||
GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld);
|
||||
|
||||
/**
|
||||
* Retrieve a subtree contained in a tree, given its
|
||||
* relative path.
|
||||
* Retrieve a tree entry contained in a tree or in any
|
||||
* of its subtrees, given its relative path.
|
||||
*
|
||||
* The returned tree is owned by the repository and
|
||||
* should be closed with the `git_object_free` method.
|
||||
* The returned tree entry is owned by the user and must
|
||||
* be freed manually with `git_tree_entry_free`.
|
||||
*
|
||||
* @param subtree Pointer where to store the subtree
|
||||
* @param entry Pointer where to store the tree entry
|
||||
* @param root A previously loaded tree which will be the root of the relative path
|
||||
* @param subtree_path Path to the contained subtree
|
||||
* @return 0 on success; GIT_ENOTFOUND if the path does not lead to a subtree
|
||||
* @param subtree_path Path to the contained entry
|
||||
* @return 0 on success; GIT_ENOTFOUND if the path does not exist
|
||||
*/
|
||||
GIT_EXTERN(int) git_tree_get_subtree(git_tree **subtree, git_tree *root, const char *subtree_path);
|
||||
GIT_EXTERN(int) git_tree_entry_bypath(
|
||||
git_tree_entry **entry,
|
||||
git_tree *root,
|
||||
const char *path);
|
||||
|
||||
/** Callback for the tree traversal method */
|
||||
typedef int (*git_treewalk_cb)(const char *root, git_tree_entry *entry, void *payload);
|
||||
typedef int (*git_treewalk_cb)(const char *root, const git_tree_entry *entry, void *payload);
|
||||
|
||||
/** Tree traversal modes */
|
||||
enum git_treewalk_mode {
|
||||
|
@ -32,6 +32,9 @@ GIT_BEGIN_DECL
|
||||
* stat() functions, for all platforms.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#ifdef __amigaos4__
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
libdir=@CMAKE_INSTALL_PREFIX@/@INSTALL_LIB@
|
||||
libdir=@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_DIR@
|
||||
includedir=@CMAKE_INSTALL_PREFIX@/@INSTALL_INC@
|
||||
|
||||
Name: libgit2
|
||||
|
@ -65,7 +65,7 @@ to compile and develop applications that use libgit2.
|
||||
cmake . \
|
||||
-DCMAKE_C_FLAGS:STRING="%{optflags}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \
|
||||
-DINSTALL_LIB:PATH=%{_libdir}
|
||||
-DLIB_INSTALL_DIR:PATH=%{_libdir}S
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
|
51
src/amiga/map.c
Executable file
51
src/amiga/map.c
Executable file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#include <git2/common.h>
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
|
||||
#include "posix.h"
|
||||
#include "map.h"
|
||||
#include <errno.h>
|
||||
|
||||
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
|
||||
{
|
||||
GIT_MMAP_VALIDATE(out, len, prot, flags);
|
||||
|
||||
out->data = NULL;
|
||||
out->len = 0;
|
||||
|
||||
if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
|
||||
giterr_set(GITERR_OS, "Trying to map shared-writeable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((out->data = malloc(len))) {
|
||||
p_lseek(fd, offset, SEEK_SET);
|
||||
p_read(fd, out->data, len);
|
||||
}
|
||||
|
||||
if (!out->data || (out->data == MAP_FAILED)) {
|
||||
giterr_set(GITERR_OS, "Failed to mmap. Could not write data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int p_munmap(git_map *map)
|
||||
{
|
||||
assert(map != NULL);
|
||||
free(map->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -5,9 +5,9 @@
|
||||
#include "git2/tree.h"
|
||||
#include <ctype.h>
|
||||
|
||||
const char *git_attr__true = "[internal]__TRUE__";
|
||||
const char *git_attr__false = "[internal]__FALSE__";
|
||||
const char *git_attr__unset = "[internal]__UNSET__";
|
||||
const char *git_l_attr__true = "[internal]__TRUE__";
|
||||
const char *git_l_attr__false = "[internal]__FALSE__";
|
||||
const char *git_l_attr__unset = "[internal]__UNSET__";
|
||||
|
||||
static int sort_by_hash_and_name(const void *a_raw, const void *b_raw);
|
||||
static void git_attr_rule__clear(git_attr_rule *rule);
|
||||
@ -503,14 +503,14 @@ int git_attr_assignment__parse(
|
||||
}
|
||||
|
||||
assign->name_hash = 5381;
|
||||
assign->value = git_attr__true;
|
||||
assign->value = git_l_attr__true;
|
||||
|
||||
/* look for magic name prefixes */
|
||||
if (*scan == '-') {
|
||||
assign->value = git_attr__false;
|
||||
assign->value = git_l_attr__false;
|
||||
scan++;
|
||||
} else if (*scan == '!') {
|
||||
assign->value = git_attr__unset; /* explicit unspecified state */
|
||||
assign->value = git_l_attr__unset; /* explicit unspecified state */
|
||||
scan++;
|
||||
} else if (*scan == '#') /* comment rest of line */
|
||||
break;
|
||||
@ -546,7 +546,7 @@ int git_attr_assignment__parse(
|
||||
}
|
||||
|
||||
/* expand macros (if given a repo with a macro cache) */
|
||||
if (repo != NULL && assign->value == git_attr__true) {
|
||||
if (repo != NULL && assign->value == git_l_attr__true) {
|
||||
git_attr_rule *macro =
|
||||
git_attr_cache__lookup_macro(repo, assign->name);
|
||||
|
||||
|
56
src/branch.c
56
src/branch.c
@ -141,46 +141,46 @@ on_error:
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
git_vector *branchlist;
|
||||
int (*branch_cb)(
|
||||
const char *branch_name,
|
||||
git_branch_t branch_type,
|
||||
void *payload);
|
||||
void *callback_payload;
|
||||
unsigned int branch_type;
|
||||
} branch_filter_data;
|
||||
} branch_foreach_filter;
|
||||
|
||||
static int branch_list_cb(const char *branch_name, void *payload)
|
||||
static int branch_foreach_cb(const char *branch_name, void *payload)
|
||||
{
|
||||
branch_filter_data *filter = (branch_filter_data *)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 git_vector_insert(filter->branchlist, git__strdup(branch_name +strlen(GIT_REFS_HEADS_DIR)));
|
||||
} else if (filter->branch_type & GIT_BRANCH_REMOTE && git__prefixcmp(branch_name, GIT_REFS_REMOTES_DIR) == 0) {
|
||||
return git_vector_insert(filter->branchlist, git__strdup(branch_name+strlen(GIT_REFS_DIR)));
|
||||
}
|
||||
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_list(git_strarray *branch_names, git_repository *repo, unsigned int list_flags)
|
||||
int git_branch_foreach(
|
||||
git_repository *repo,
|
||||
unsigned int list_flags,
|
||||
int (*branch_cb)(
|
||||
const char *branch_name,
|
||||
git_branch_t branch_type,
|
||||
void *payload),
|
||||
void *payload
|
||||
)
|
||||
{
|
||||
int error;
|
||||
branch_filter_data filter;
|
||||
git_vector branchlist;
|
||||
branch_foreach_filter filter;
|
||||
|
||||
assert(branch_names && repo);
|
||||
|
||||
if (git_vector_init(&branchlist, 8, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
filter.branchlist = &branchlist;
|
||||
filter.branch_cb = branch_cb;
|
||||
filter.branch_type = list_flags;
|
||||
filter.callback_payload = payload;
|
||||
|
||||
error = git_reference_foreach(repo, GIT_REF_LISTALL, &branch_list_cb, (void *)&filter);
|
||||
if (error < 0) {
|
||||
git_vector_free(&branchlist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
branch_names->strings = (char **)branchlist.contents;
|
||||
branch_names->count = branchlist.length;
|
||||
return 0;
|
||||
return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
|
||||
}
|
||||
|
||||
int git_branch_move(git_repository *repo, const char *old_branch_name, const char *new_branch_name, int force)
|
||||
|
36
src/buffer.c
36
src/buffer.c
@ -141,6 +141,42 @@ int git_buf_puts(git_buf *buf, const char *string)
|
||||
return git_buf_put(buf, string, strlen(string));
|
||||
}
|
||||
|
||||
int git_buf_puts_escaped(
|
||||
git_buf *buf, const char *string, const char *esc_chars, const char *esc_with)
|
||||
{
|
||||
const char *scan = string;
|
||||
size_t total = 0, esc_with_len = strlen(esc_with);
|
||||
|
||||
while (*scan) {
|
||||
size_t count = strcspn(scan, esc_chars);
|
||||
total += count + 1 + esc_with_len;
|
||||
scan += count + 1;
|
||||
}
|
||||
|
||||
ENSURE_SIZE(buf, buf->size + total + 1);
|
||||
|
||||
for (scan = string; *scan; ) {
|
||||
size_t count = strcspn(scan, esc_chars);
|
||||
|
||||
memmove(buf->ptr + buf->size, scan, count);
|
||||
scan += count;
|
||||
buf->size += count;
|
||||
|
||||
if (*scan) {
|
||||
memmove(buf->ptr + buf->size, esc_with, esc_with_len);
|
||||
buf->size += esc_with_len;
|
||||
|
||||
memmove(buf->ptr + buf->size, scan, 1);
|
||||
scan += 1;
|
||||
buf->size += 1;
|
||||
}
|
||||
}
|
||||
|
||||
buf->ptr[buf->size] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
|
||||
{
|
||||
int len;
|
||||
|
19
src/buffer.h
19
src/buffer.h
@ -90,6 +90,18 @@ void git_buf_rtruncate_at_char(git_buf *path, char separator);
|
||||
int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...);
|
||||
int git_buf_join(git_buf *buf, char separator, const char *str_a, const char *str_b);
|
||||
|
||||
/**
|
||||
* Copy string into buf prefixing every character that is contained in the
|
||||
* esc_chars string with the esc_with string.
|
||||
*/
|
||||
int git_buf_puts_escaped(
|
||||
git_buf *buf, const char *string, const char *esc_chars, const char *esc_with);
|
||||
|
||||
GIT_INLINE(int) git_buf_puts_escape_regex(git_buf *buf, const char *string)
|
||||
{
|
||||
return git_buf_puts_escaped(buf, string, "^.[]$()|*+?{}\\", "\\");
|
||||
}
|
||||
|
||||
/**
|
||||
* Join two strings as paths, inserting a slash between as needed.
|
||||
* @return 0 on success, -1 on failure
|
||||
@ -121,6 +133,13 @@ GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
|
||||
return idx;
|
||||
}
|
||||
|
||||
GIT_INLINE(ssize_t) git_buf_rfind(git_buf *buf, char ch)
|
||||
{
|
||||
ssize_t idx = (ssize_t)buf->size - 1;
|
||||
while (idx >= 0 && buf->ptr[idx] != ch) idx--;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Remove whitespace from the end of the buffer */
|
||||
void git_buf_rtrim(git_buf *buf);
|
||||
|
||||
|
63
src/commit.c
63
src/commit.c
@ -229,30 +229,63 @@ GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset)
|
||||
GIT_COMMIT_GETTER(unsigned int, parentcount, commit->parent_oids.length)
|
||||
GIT_COMMIT_GETTER(const git_oid *, tree_oid, &commit->tree_oid);
|
||||
|
||||
|
||||
int git_commit_tree(git_tree **tree_out, git_commit *commit)
|
||||
{
|
||||
assert(commit);
|
||||
return git_tree_lookup(tree_out, commit->object.repo, &commit->tree_oid);
|
||||
}
|
||||
|
||||
int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
|
||||
{
|
||||
git_oid *parent_oid;
|
||||
assert(commit);
|
||||
|
||||
parent_oid = git_vector_get(&commit->parent_oids, n);
|
||||
if (parent_oid == NULL) {
|
||||
giterr_set(GITERR_INVALID, "Parent %u does not exist", n);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
return git_commit_lookup(parent, commit->object.repo, parent_oid);
|
||||
}
|
||||
|
||||
const git_oid *git_commit_parent_oid(git_commit *commit, unsigned int n)
|
||||
{
|
||||
assert(commit);
|
||||
|
||||
return git_vector_get(&commit->parent_oids, n);
|
||||
}
|
||||
|
||||
int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
|
||||
{
|
||||
const git_oid *parent_oid;
|
||||
assert(commit);
|
||||
|
||||
parent_oid = git_commit_parent_oid(commit, n);
|
||||
if (parent_oid == NULL) {
|
||||
giterr_set(GITERR_INVALID, "Parent %u does not exist", n);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
return git_commit_lookup(parent, commit->object.repo, parent_oid);
|
||||
}
|
||||
|
||||
int git_commit_nth_gen_ancestor(
|
||||
git_commit **ancestor,
|
||||
const git_commit *commit,
|
||||
unsigned int n)
|
||||
{
|
||||
git_commit *current, *parent;
|
||||
int error;
|
||||
|
||||
assert(ancestor && commit);
|
||||
|
||||
current = (git_commit *)commit;
|
||||
|
||||
if (n == 0)
|
||||
return git_commit_lookup(
|
||||
ancestor,
|
||||
commit->object.repo,
|
||||
git_object_id((const git_object *)commit));
|
||||
|
||||
while (n--) {
|
||||
error = git_commit_parent(&parent, (git_commit *)current, 0);
|
||||
|
||||
if (current != commit)
|
||||
git_commit_free(current);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
current = parent;
|
||||
}
|
||||
|
||||
*ancestor = parent;
|
||||
return 0;
|
||||
}
|
||||
|
16
src/config.c
16
src/config.c
@ -136,17 +136,27 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
|
||||
* Loop over all the variables
|
||||
*/
|
||||
|
||||
int git_config_foreach(git_config *cfg, int (*fn)(const char *, const char *, void *), void *data)
|
||||
int git_config_foreach(
|
||||
git_config *cfg, int (*fn)(const char *, const char *, void *), void *data)
|
||||
{
|
||||
return git_config_foreach_match(cfg, NULL, fn, data);
|
||||
}
|
||||
|
||||
int git_config_foreach_match(
|
||||
git_config *cfg,
|
||||
const char *regexp,
|
||||
int (*fn)(const char *, const char *, void *),
|
||||
void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int i;
|
||||
file_internal *internal;
|
||||
git_config_file *file;
|
||||
|
||||
for(i = 0; i < cfg->files.length && ret == 0; ++i) {
|
||||
for (i = 0; i < cfg->files.length && ret == 0; ++i) {
|
||||
internal = git_vector_get(&cfg->files, i);
|
||||
file = internal->file;
|
||||
ret = file->foreach(file, fn, data);
|
||||
ret = file->foreach(file, regexp, fn, data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -188,25 +188,46 @@ static void backend_free(git_config_file *_backend)
|
||||
git__free(backend);
|
||||
}
|
||||
|
||||
static int file_foreach(git_config_file *backend, int (*fn)(const char *, const char *, void *), void *data)
|
||||
static int file_foreach(
|
||||
git_config_file *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const char *, const char *, void *),
|
||||
void *data)
|
||||
{
|
||||
diskfile_backend *b = (diskfile_backend *)backend;
|
||||
cvar_t *var;
|
||||
const char *key;
|
||||
regex_t regex;
|
||||
int result = 0;
|
||||
|
||||
if (!b->values)
|
||||
return 0;
|
||||
|
||||
git_strmap_foreach(b->values, key, var,
|
||||
do {
|
||||
if (fn(key, var->value, data) < 0)
|
||||
break;
|
||||
if (regexp != NULL) {
|
||||
if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(®ex, result);
|
||||
regfree(®ex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
var = CVAR_LIST_NEXT(var);
|
||||
} while (var != NULL);
|
||||
git_strmap_foreach(b->values, key, var,
|
||||
for (; var != NULL; var = CVAR_LIST_NEXT(var)) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexp && regexec(®ex, key, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if ((result = fn(key, var->value, data)) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
);
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
if (regexp != NULL)
|
||||
regfree(®ex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int config_set(git_config_file *cfg, const char *name, const char *value)
|
||||
@ -337,6 +358,7 @@ static int config_get_multivar(
|
||||
result = regcomp(®ex, regex_str, REG_EXTENDED);
|
||||
if (result < 0) {
|
||||
giterr_set_regex(®ex, result);
|
||||
regfree(®ex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -396,6 +418,7 @@ static int config_set_multivar(
|
||||
if (result < 0) {
|
||||
git__free(key);
|
||||
giterr_set_regex(&preg, result);
|
||||
regfree(&preg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,27 @@ GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
|
||||
cfg->free(cfg);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_config_file_set_string(
|
||||
git_config_file *cfg, const char *name, const char *value)
|
||||
{
|
||||
return cfg->set(cfg, name, value);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_config_file_foreach(
|
||||
git_config_file *cfg,
|
||||
int (*fn)(const char *key, const char *value, void *data),
|
||||
void *data)
|
||||
{
|
||||
return cfg->foreach(cfg, fn, data);
|
||||
return cfg->foreach(cfg, NULL, fn, data);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_config_file_foreach_match(
|
||||
git_config_file *cfg,
|
||||
const char *regexp,
|
||||
int (*fn)(const char *key, const char *value, void *data),
|
||||
void *data)
|
||||
{
|
||||
return cfg->foreach(cfg, regexp, fn, data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -212,7 +212,7 @@ static void setup_xdiff_options(
|
||||
cfg->ctxlen =
|
||||
(!opts || !opts->context_lines) ? 3 : opts->context_lines;
|
||||
cfg->interhunkctxlen =
|
||||
(!opts || !opts->interhunk_lines) ? 3 : opts->interhunk_lines;
|
||||
(!opts) ? 0 : opts->interhunk_lines;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
|
@ -118,7 +118,8 @@ int git_fetch__download_pack(
|
||||
int recvd;
|
||||
char buff[1024];
|
||||
gitno_buffer buf;
|
||||
git_indexer_stream *idx;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
git_indexer_stream *idx = NULL;
|
||||
|
||||
gitno_buffer_setup(t, &buf, buff, sizeof(buff));
|
||||
|
||||
@ -127,9 +128,12 @@ int git_fetch__download_pack(
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_indexer_stream_new(&idx, git_repository_path(repo)) < 0)
|
||||
if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0)
|
||||
return -1;
|
||||
|
||||
if (git_indexer_stream_new(&idx, git_buf_cstr(&path)) < 0)
|
||||
goto on_error;
|
||||
|
||||
memset(stats, 0, sizeof(git_indexer_stats));
|
||||
if (git_indexer_stream_add(idx, buffered, buffered_size, stats) < 0)
|
||||
goto on_error;
|
||||
@ -154,6 +158,7 @@ int git_fetch__download_pack(
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git_buf_free(&path);
|
||||
git_indexer_stream_free(idx);
|
||||
return -1;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ int git_futils_open_ro(const char *path)
|
||||
{
|
||||
int fd = p_open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT)
|
||||
if (errno == ENOENT || errno == ENOTDIR)
|
||||
fd = GIT_ENOTFOUND;
|
||||
giterr_set(GITERR_OS, "Failed to open '%s'", path);
|
||||
}
|
||||
|
@ -985,7 +985,7 @@ int git_index_entry_stage(const git_index_entry *entry)
|
||||
return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT;
|
||||
}
|
||||
|
||||
static int read_tree_cb(const char *root, git_tree_entry *tentry, void *data)
|
||||
static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *data)
|
||||
{
|
||||
git_index *index = data;
|
||||
git_index_entry *entry = NULL;
|
||||
|
@ -142,7 +142,7 @@ int git_indexer_stream_new(git_indexer_stream **out, const char *prefix)
|
||||
{
|
||||
git_indexer_stream *idx;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
static const char suff[] = "/objects/pack/pack-received";
|
||||
static const char suff[] = "/pack";
|
||||
int error;
|
||||
|
||||
idx = git__calloc(1, sizeof(git_indexer_stream));
|
||||
@ -169,29 +169,14 @@ cleanup:
|
||||
}
|
||||
|
||||
/* Try to store the delta so we can try to resolve it later */
|
||||
static int store_delta(git_indexer_stream *idx)
|
||||
static int store_delta(git_indexer_stream *idx, git_off_t entry_start, size_t entry_size, git_otype type)
|
||||
{
|
||||
git_otype type;
|
||||
git_mwindow *w = NULL;
|
||||
git_mwindow_file *mwf = &idx->pack->mwf;
|
||||
git_off_t entry_start = idx->off;
|
||||
struct delta_info *delta;
|
||||
size_t entry_size;
|
||||
git_rawobj obj;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* ref-delta objects can refer to object that we haven't
|
||||
* found yet, so give it another opportunity
|
||||
*/
|
||||
if (git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off) < 0)
|
||||
return -1;
|
||||
|
||||
git_mwindow_close(&w);
|
||||
|
||||
/* If it's not a delta, mark it as failure, we can't do anything with it */
|
||||
if (type != GIT_OBJ_REF_DELTA && type != GIT_OBJ_OFS_DELTA)
|
||||
return -1;
|
||||
assert(type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA);
|
||||
|
||||
if (type == GIT_OBJ_REF_DELTA) {
|
||||
idx->off += GIT_OID_RAWSZ;
|
||||
@ -313,8 +298,6 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
||||
mwf = &idx->pack->mwf;
|
||||
if (git_mwindow_file_register(&idx->pack->mwf) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!idx->parsed_header) {
|
||||
@ -352,27 +335,44 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
|
||||
while (processed < idx->nr_objects) {
|
||||
git_rawobj obj;
|
||||
git_off_t entry_start = idx->off;
|
||||
size_t entry_size;
|
||||
git_otype type;
|
||||
git_mwindow *w = NULL;
|
||||
|
||||
if (idx->pack->mwf.size <= idx->off + 20)
|
||||
return 0;
|
||||
|
||||
error = git_packfile_unpack(&obj, idx->pack, &idx->off);
|
||||
error = git_packfile_unpack_header(&entry_size, &type, mwf, &w, &idx->off);
|
||||
if (error == GIT_EBUFS) {
|
||||
idx->off = entry_start;
|
||||
return 0;
|
||||
}
|
||||
if (error < 0)
|
||||
return -1;
|
||||
|
||||
if (error < 0) {
|
||||
idx->off = entry_start;
|
||||
error = store_delta(idx);
|
||||
if (error == GIT_EBUFS)
|
||||
git_mwindow_close(&w);
|
||||
|
||||
if (type == GIT_OBJ_REF_DELTA || type == GIT_OBJ_OFS_DELTA) {
|
||||
error = store_delta(idx, entry_start, entry_size, type);
|
||||
if (error == GIT_EBUFS) {
|
||||
idx->off = entry_start;
|
||||
return 0;
|
||||
}
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
idx->off = entry_start;
|
||||
error = git_packfile_unpack(&obj, idx->pack, &idx->off);
|
||||
if (error == GIT_EBUFS) {
|
||||
idx->off = entry_start;
|
||||
return 0;
|
||||
}
|
||||
if (error < 0)
|
||||
return -1;
|
||||
|
||||
if (hash_and_save(idx, &obj, entry_start) < 0)
|
||||
goto on_error;
|
||||
|
||||
@ -775,6 +775,7 @@ int git_indexer_write(git_indexer *idx)
|
||||
|
||||
cleanup:
|
||||
git_mwindow_free_all(&idx->pack->mwf);
|
||||
git_mwindow_file_deregister(&idx->pack->mwf);
|
||||
if (error < 0)
|
||||
git_filebuf_cleanup(&idx->file);
|
||||
git_buf_free(&filename);
|
||||
@ -888,6 +889,7 @@ void git_indexer_free(git_indexer *idx)
|
||||
return;
|
||||
|
||||
p_close(idx->pack->mwf.fd);
|
||||
git_mwindow_file_deregister(&idx->pack->mwf);
|
||||
git_vector_foreach(&idx->objects, i, e)
|
||||
git__free(e);
|
||||
git_vector_free(&idx->objects);
|
||||
|
10
src/khash.h
10
src/khash.h
@ -131,7 +131,9 @@ typedef unsigned long long khint64_t;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#define kh_inline __inline
|
||||
#else
|
||||
#define kh_inline inline
|
||||
#endif
|
||||
|
||||
typedef khint32_t khint_t;
|
||||
@ -345,7 +347,7 @@ static const double __ac_HASH_UPPER = 0.77;
|
||||
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
|
||||
|
||||
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
KHASH_INIT2(name, static inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
|
||||
KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
|
||||
|
||||
/* --- BEGIN OF HASH FUNCTIONS --- */
|
||||
|
||||
@ -374,7 +376,7 @@ static const double __ac_HASH_UPPER = 0.77;
|
||||
@param s Pointer to a null terminated string
|
||||
@return The hash value
|
||||
*/
|
||||
static inline khint_t __ac_X31_hash_string(const char *s)
|
||||
static kh_inline khint_t __ac_X31_hash_string(const char *s)
|
||||
{
|
||||
khint_t h = (khint_t)*s;
|
||||
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
|
||||
@ -391,7 +393,7 @@ static inline khint_t __ac_X31_hash_string(const char *s)
|
||||
*/
|
||||
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
|
||||
|
||||
static inline khint_t __ac_Wang_hash(khint_t key)
|
||||
static kh_inline khint_t __ac_Wang_hash(khint_t key)
|
||||
{
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
|
@ -23,6 +23,10 @@
|
||||
#define GIT_MAP_TYPE 0xf
|
||||
#define GIT_MAP_FIXED 0x10
|
||||
|
||||
#ifdef __amigaos4__
|
||||
#define MAP_FAILED 0
|
||||
#endif
|
||||
|
||||
typedef struct { /* memory mapped buffer */
|
||||
void *data; /* data bytes */
|
||||
size_t len; /* data length */
|
||||
|
@ -158,6 +158,7 @@ static git_mwindow *new_window(
|
||||
git_mwindow *w;
|
||||
|
||||
w = git__malloc(sizeof(*w));
|
||||
|
||||
if (w == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -260,6 +261,23 @@ int git_mwindow_file_register(git_mwindow_file *mwf)
|
||||
return git_vector_insert(&ctl->windowfiles, mwf);
|
||||
}
|
||||
|
||||
int git_mwindow_file_deregister(git_mwindow_file *mwf)
|
||||
{
|
||||
git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
|
||||
git_mwindow_file *cur;
|
||||
unsigned int i;
|
||||
|
||||
git_vector_foreach(&ctl->windowfiles, i, cur) {
|
||||
if (cur == mwf) {
|
||||
git_vector_remove(&ctl->windowfiles, i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
giterr_set(GITERR_ODB, "Failed to find the memory window file to deregister");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_mwindow_close(git_mwindow **window)
|
||||
{
|
||||
git_mwindow *w = *window;
|
||||
|
@ -40,6 +40,7 @@ void git_mwindow_free_all(git_mwindow_file *mwf);
|
||||
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, size_t extra, unsigned int *left);
|
||||
void git_mwindow_scan_lru(git_mwindow_file *mwf, git_mwindow **lru_w, git_mwindow **lru_l);
|
||||
int git_mwindow_file_register(git_mwindow_file *mwf);
|
||||
int git_mwindow_file_deregister(git_mwindow_file *mwf);
|
||||
void git_mwindow_close(git_mwindow **w_cursor);
|
||||
|
||||
#endif
|
||||
|
10
src/netops.c
10
src/netops.c
@ -381,16 +381,18 @@ int gitno_connect(git_transport *t, const char *host, const char *port)
|
||||
GIT_SOCKET s = INVALID_SOCKET;
|
||||
|
||||
memset(&hints, 0x0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
if ((ret = getaddrinfo(host, port, &hints, &info)) < 0) {
|
||||
giterr_set(GITERR_NET, "Failed to resolve address for %s: %s", host, gai_strerror(ret));
|
||||
if ((ret = p_getaddrinfo(host, port, &hints, &info)) < 0) {
|
||||
giterr_set(GITERR_NET,
|
||||
"Failed to resolve address for %s: %s", host, p_gai_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (p = info; p != NULL; p = p->ai_next) {
|
||||
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
|
||||
if (s == INVALID_SOCKET) {
|
||||
net_set_error("error creating socket");
|
||||
break;
|
||||
@ -411,7 +413,7 @@ int gitno_connect(git_transport *t, const char *host, const char *port)
|
||||
}
|
||||
|
||||
t->socket = s;
|
||||
freeaddrinfo(info);
|
||||
p_freeaddrinfo(info);
|
||||
|
||||
if (t->encrypt && ssl_setup(t, host) < 0)
|
||||
return -1;
|
||||
|
22
src/notes.c
22
src/notes.c
@ -56,7 +56,7 @@ static int find_subtree_r(git_tree **out, git_tree *root,
|
||||
|
||||
error = find_subtree_in_current_level(&subtree, repo, root, target, *fanout);
|
||||
if (error == GIT_EEXISTS) {
|
||||
return git_tree_lookup(out, repo, git_object_id((const git_object *)root));
|
||||
return git_tree_lookup(out, repo, git_tree_id(root));
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
@ -64,13 +64,7 @@ static int find_subtree_r(git_tree **out, git_tree *root,
|
||||
|
||||
*fanout += 2;
|
||||
error = find_subtree_r(out, subtree, repo, target, fanout);
|
||||
|
||||
/*
|
||||
* root is not ours to free, and the last subtree is the
|
||||
* one being returned => we only need to free the subtrees in-between
|
||||
*/
|
||||
if (*out != subtree)
|
||||
git_tree_free(subtree);
|
||||
git_tree_free(subtree);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -103,7 +97,7 @@ static int tree_write(
|
||||
{
|
||||
int error;
|
||||
git_treebuilder *tb = NULL;
|
||||
git_tree_entry *entry;
|
||||
const git_tree_entry *entry;
|
||||
git_oid tree_oid;
|
||||
|
||||
if ((error = git_treebuilder_create(&tb, source_tree)) < 0)
|
||||
@ -153,7 +147,7 @@ static int manipulate_note_in_tree_r(
|
||||
int current_error))
|
||||
{
|
||||
int error = -1;
|
||||
git_tree *subtree = NULL;
|
||||
git_tree *subtree = NULL, *new = NULL;
|
||||
char subtree_name[3];
|
||||
|
||||
error = find_subtree_in_current_level(
|
||||
@ -176,7 +170,7 @@ static int manipulate_note_in_tree_r(
|
||||
|
||||
/* An existing fanout has been found, let's dig deeper */
|
||||
error = manipulate_note_in_tree_r(
|
||||
out, repo, subtree, note_oid, annotated_object_sha,
|
||||
&new, repo, subtree, note_oid, annotated_object_sha,
|
||||
fanout + 2, note_exists_cb, note_notfound_cb);
|
||||
|
||||
if (error < 0)
|
||||
@ -185,10 +179,12 @@ static int manipulate_note_in_tree_r(
|
||||
strncpy(subtree_name, annotated_object_sha + fanout, 2);
|
||||
subtree_name[2] = '\0';
|
||||
|
||||
error = tree_write(out, repo, parent,
|
||||
git_object_id((const git_object *)(*out)), subtree_name, 0040000);
|
||||
error = tree_write(out, repo, parent, git_tree_id(new),
|
||||
subtree_name, 0040000);
|
||||
|
||||
|
||||
cleanup:
|
||||
git_tree_free(new);
|
||||
git_tree_free(subtree);
|
||||
return error;
|
||||
}
|
||||
|
@ -156,8 +156,10 @@ int git_object_lookup_prefix(
|
||||
|
||||
type = odb_obj->raw.type;
|
||||
|
||||
if (create_object(&object, type) < 0)
|
||||
if (create_object(&object, type) < 0) {
|
||||
git_odb_object_free(odb_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize parent object */
|
||||
git_oid_cpy(&object->cached.oid, &odb_obj->cached.oid);
|
||||
|
12
src/odb.c
12
src/odb.c
@ -605,6 +605,18 @@ int git_odb_read_prefix(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data)
|
||||
{
|
||||
unsigned int i;
|
||||
backend_internal *internal;
|
||||
git_vector_foreach(&db->backends, i, internal) {
|
||||
git_odb_backend *b = internal->backend;
|
||||
b->foreach(b, cb, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_odb_write(
|
||||
git_oid *oid, git_odb *db, const void *data, size_t len, git_otype type)
|
||||
{
|
||||
|
@ -676,6 +676,89 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
|
||||
return !error;
|
||||
}
|
||||
|
||||
struct foreach_state {
|
||||
size_t dir_len;
|
||||
int (*cb)(git_oid *oid, void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
{
|
||||
int v, i = 0;
|
||||
if (strlen(ptr) != 41)
|
||||
return -1;
|
||||
|
||||
if (ptr[2] != '/') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
v = (git__fromhex(ptr[i]) << 4) | git__fromhex(ptr[i+1]);
|
||||
if (v < 0)
|
||||
return -1;
|
||||
|
||||
oid->id[0] = (unsigned char) v;
|
||||
|
||||
ptr += 3;
|
||||
for (i = 0; i < 38; i += 2) {
|
||||
v = (git__fromhex(ptr[i]) << 4) | git__fromhex(ptr[i + 1]);
|
||||
if (v < 0)
|
||||
return -1;
|
||||
|
||||
oid->id[1 + i/2] = (unsigned char) v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int foreach_object_dir_cb(void *_state, git_buf *path)
|
||||
{
|
||||
git_oid oid;
|
||||
struct foreach_state *state = (struct foreach_state *) _state;
|
||||
|
||||
if (filename_to_oid(&oid, path->ptr + state->dir_len) < 0)
|
||||
return 0;
|
||||
|
||||
if (state->cb(&oid, state->data) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int foreach_cb(void *_state, git_buf *path)
|
||||
{
|
||||
struct foreach_state *state = (struct foreach_state *) _state;
|
||||
|
||||
if (git_path_direach(path, foreach_object_dir_cb, state) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loose_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *oid, void *data), void *data)
|
||||
{
|
||||
char *objects_dir;
|
||||
int error;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
struct foreach_state state;
|
||||
loose_backend *backend = (loose_backend *) _backend;
|
||||
|
||||
assert(backend && cb);
|
||||
|
||||
objects_dir = backend->objects_dir;
|
||||
|
||||
git_buf_sets(&buf, objects_dir);
|
||||
git_path_to_dir(&buf);
|
||||
|
||||
state.cb = cb;
|
||||
state.data = data;
|
||||
state.dir_len = git_buf_len(&buf);
|
||||
|
||||
error = git_path_direach(&buf, foreach_cb, &state);
|
||||
git_buf_free(&buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
|
||||
{
|
||||
loose_writestream *stream = (loose_writestream *)_stream;
|
||||
@ -845,6 +928,7 @@ int git_odb_backend_loose(
|
||||
backend->parent.read_header = &loose_backend__read_header;
|
||||
backend->parent.writestream = &loose_backend__stream;
|
||||
backend->parent.exists = &loose_backend__exists;
|
||||
backend->parent.foreach = &loose_backend__foreach;
|
||||
backend->parent.free = &loose_backend__free;
|
||||
|
||||
*backend_out = (git_odb_backend *)backend;
|
||||
|
@ -420,6 +420,25 @@ static int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
|
||||
return pack_entry_find(&e, (struct pack_backend *)backend, oid) == 0;
|
||||
}
|
||||
|
||||
static int pack_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *oid, void *data), void *data)
|
||||
{
|
||||
struct git_pack_file *p;
|
||||
struct pack_backend *backend;
|
||||
unsigned int i;
|
||||
|
||||
assert(_backend && cb);
|
||||
backend = (struct pack_backend *)_backend;
|
||||
|
||||
/* Make sure we know about the packfiles */
|
||||
if (packfile_refresh_all(backend) < 0)
|
||||
return -1;
|
||||
|
||||
git_vector_foreach(&backend->packs, i, p) {
|
||||
git_pack_foreach_entry(p, cb, &data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pack_backend__free(git_odb_backend *_backend)
|
||||
{
|
||||
struct pack_backend *backend;
|
||||
@ -463,6 +482,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
|
||||
backend->parent.read_prefix = &pack_backend__read_prefix;
|
||||
backend->parent.read_header = NULL;
|
||||
backend->parent.exists = &pack_backend__exists;
|
||||
backend->parent.foreach = &pack_backend__foreach;
|
||||
backend->parent.free = &pack_backend__free;
|
||||
|
||||
*backend_out = (git_odb_backend *)backend;
|
||||
|
@ -34,7 +34,7 @@ GIT_INLINE(int) hash_git_oid_equal(const git_oid *a, const git_oid *b)
|
||||
}
|
||||
|
||||
#define GIT__USE_OIDMAP \
|
||||
__KHASH_IMPL(oid, static inline, const git_oid *, void *, 1, hash_git_oid, hash_git_oid_equal)
|
||||
__KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, hash_git_oid, hash_git_oid_equal)
|
||||
|
||||
#define git_oidmap_alloc() kh_init(oid)
|
||||
#define git_oidmap_free(h) kh_destroy(oid,h), h = NULL
|
||||
|
46
src/pack.c
46
src/pack.c
@ -262,7 +262,7 @@ int git_packfile_unpack_header(
|
||||
if (base == NULL)
|
||||
return GIT_EBUFS;
|
||||
|
||||
ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
|
||||
ret = packfile_unpack_header1(&used, size_p, type_p, base, left);
|
||||
git_mwindow_close(w_curs);
|
||||
if (ret == GIT_EBUFS)
|
||||
return ret;
|
||||
@ -535,6 +535,7 @@ void packfile_free(struct git_pack_file *p)
|
||||
|
||||
/* clear_delta_base_cache(); */
|
||||
git_mwindow_free_all(&p->mwf);
|
||||
git_mwindow_file_deregister(&p->mwf);
|
||||
|
||||
if (p->mwf.fd != -1)
|
||||
p_close(p->mwf.fd);
|
||||
@ -685,6 +686,49 @@ static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_
|
||||
}
|
||||
}
|
||||
|
||||
int git_pack_foreach_entry(
|
||||
struct git_pack_file *p,
|
||||
int (*cb)(git_oid *oid, void *data),
|
||||
void *data)
|
||||
|
||||
{
|
||||
const unsigned char *index = p->index_map.data, *current;
|
||||
unsigned stride;
|
||||
uint32_t i;
|
||||
|
||||
if (index == NULL) {
|
||||
int error;
|
||||
|
||||
if ((error = pack_index_open(p)) < 0)
|
||||
return error;
|
||||
|
||||
assert(p->index_map.data);
|
||||
|
||||
index = p->index_map.data;
|
||||
}
|
||||
|
||||
if (p->index_version > 1) {
|
||||
index += 8;
|
||||
}
|
||||
|
||||
index += 4 * 256;
|
||||
|
||||
if (p->index_version > 1) {
|
||||
stride = 20;
|
||||
} else {
|
||||
stride = 24;
|
||||
index += 4;
|
||||
}
|
||||
|
||||
current = index;
|
||||
for (i = 0; i < p->num_objects; i++) {
|
||||
cb((git_oid *)current, data);
|
||||
current += stride;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pack_entry_find_offset(
|
||||
git_off_t *offset_out,
|
||||
git_oid *found_oid,
|
||||
|
@ -102,5 +102,9 @@ int git_pack_entry_find(
|
||||
struct git_pack_file *p,
|
||||
const git_oid *short_oid,
|
||||
unsigned int len);
|
||||
int git_pack_foreach_entry(
|
||||
struct git_pack_file *p,
|
||||
int (*cb)(git_oid *oid, void *data),
|
||||
void *data);
|
||||
|
||||
#endif
|
||||
|
73
src/path.c
73
src/path.c
@ -17,9 +17,7 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
#define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':')
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Based on the Android implementation, BSD licensed.
|
||||
@ -172,11 +170,11 @@ int git_path_root(const char *path)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
/* Does the root of the path look like a windows drive ? */
|
||||
if (LOOKS_LIKE_DRIVE_PREFIX(path))
|
||||
offset += 2;
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
/* Are we dealing with a windows network path? */
|
||||
else if ((path[0] == '/' && path[1] == '/') ||
|
||||
(path[0] == '\\' && path[1] == '\\'))
|
||||
@ -527,6 +525,71 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base)
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_path_resolve_relative(git_buf *path, size_t ceiling)
|
||||
{
|
||||
char *base, *to, *from, *next;
|
||||
size_t len;
|
||||
|
||||
if (!path || git_buf_oom(path))
|
||||
return -1;
|
||||
|
||||
if (ceiling > path->size)
|
||||
ceiling = path->size;
|
||||
|
||||
/* recognize drive prefixes, etc. that should not be backed over */
|
||||
if (ceiling == 0)
|
||||
ceiling = git_path_root(path->ptr) + 1;
|
||||
|
||||
/* recognize URL prefixes that should not be backed over */
|
||||
if (ceiling == 0) {
|
||||
for (next = path->ptr; *next && git__isalpha(*next); ++next);
|
||||
if (next[0] == ':' && next[1] == '/' && next[2] == '/')
|
||||
ceiling = (next + 3) - path->ptr;
|
||||
}
|
||||
|
||||
base = to = from = path->ptr + ceiling;
|
||||
|
||||
while (*from) {
|
||||
for (next = from; *next && *next != '/'; ++next);
|
||||
|
||||
len = next - from;
|
||||
|
||||
if (len == 1 && from[0] == '.')
|
||||
/* do nothing with singleton dot */;
|
||||
|
||||
else if (len == 2 && from[0] == '.' && from[1] == '.') {
|
||||
while (to > base && to[-1] == '/') to--;
|
||||
while (to > base && to[-1] != '/') to--;
|
||||
}
|
||||
|
||||
else {
|
||||
if (*next == '/')
|
||||
len++;
|
||||
|
||||
if (to != from)
|
||||
memmove(to, from, len);
|
||||
|
||||
to += len;
|
||||
}
|
||||
|
||||
from += len;
|
||||
|
||||
while (*from == '/') from++;
|
||||
}
|
||||
|
||||
*to = '\0';
|
||||
|
||||
path->size = to - path->ptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_path_apply_relative(git_buf *target, const char *relpath)
|
||||
{
|
||||
git_buf_joinpath(target, git_buf_cstr(target), relpath);
|
||||
return git_path_resolve_relative(target, 0);
|
||||
}
|
||||
|
||||
int git_path_cmp(
|
||||
const char *name1, size_t len1, int isdir1,
|
||||
const char *name2, size_t len2, int isdir2)
|
||||
@ -570,7 +633,7 @@ int git_path_direach(
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
#if defined(__sun) || defined(__GNU__)
|
||||
de_buf = git__malloc(sizeof(struct dirent) + FILENAME_MAX + 1);
|
||||
#else
|
||||
de_buf = git__malloc(sizeof(struct dirent));
|
||||
@ -624,7 +687,7 @@ int git_path_dirload(
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
#if defined(__sun) || defined(__GNU__)
|
||||
de_buf = git__malloc(sizeof(struct dirent) + FILENAME_MAX + 1);
|
||||
#else
|
||||
de_buf = git__malloc(sizeof(struct dirent));
|
||||
|
23
src/path.h
23
src/path.h
@ -207,6 +207,29 @@ extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char
|
||||
*/
|
||||
extern int git_path_find_dir(git_buf *dir, const char *path, const char *base);
|
||||
|
||||
/**
|
||||
* Resolve relative references within a path.
|
||||
*
|
||||
* This eliminates "./" and "../" relative references inside a path,
|
||||
* as well as condensing multiple slashes into single ones. It will
|
||||
* not touch the path before the "ceiling" length.
|
||||
*
|
||||
* Additionally, this will recognize an "c:/" drive prefix or a "xyz://" URL
|
||||
* prefix and not touch that part of the path.
|
||||
*/
|
||||
extern int git_path_resolve_relative(git_buf *path, size_t ceiling);
|
||||
|
||||
/**
|
||||
* Apply a relative path to base path.
|
||||
*
|
||||
* Note that the base path could be a filename or a URL and this
|
||||
* should still work. The relative path is walked segment by segment
|
||||
* with three rules: series of slashes will be condensed to a single
|
||||
* slash, "." will be eaten with no change, and ".." will remove a
|
||||
* segment from the base path.
|
||||
*/
|
||||
extern int git_path_apply_relative(git_buf *target, const char *relpath);
|
||||
|
||||
/**
|
||||
* Walk each directory entry, except '.' and '..', calling fn(state).
|
||||
*
|
||||
|
@ -296,7 +296,7 @@ static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps
|
||||
git_buf_grow(buf, git_buf_len(buf) + len);
|
||||
|
||||
git_oid_fmt(oid, &head->oid);
|
||||
return git_buf_printf(buf, "%04xwant %s%c%s\n", len, oid, 0, capstr);
|
||||
return git_buf_printf(buf, "%04xwant %s %s\n", len, oid, capstr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -275,6 +275,8 @@ uint32_t git_pool__system_page_size(void)
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
size = (uint32_t)info.dwPageSize;
|
||||
#elif defined(__amigaos4__)
|
||||
size = (uint32_t)4096; /* 4K as there is no global value we can query */
|
||||
#else
|
||||
size = (uint32_t)sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
|
93
src/posix.c
93
src/posix.c
@ -12,6 +12,97 @@
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
|
||||
#ifdef NO_ADDRINFO
|
||||
int p_getaddrinfo(
|
||||
const char *host,
|
||||
const char *port,
|
||||
struct addrinfo *hints,
|
||||
struct addrinfo **info)
|
||||
{
|
||||
GIT_UNUSED(hints);
|
||||
|
||||
struct addrinfo *ainfo, *ai;
|
||||
int p = 0;
|
||||
|
||||
if ((ainfo = malloc(sizeof(struct addrinfo))) == NULL)
|
||||
return -1;
|
||||
|
||||
if ((ainfo->ai_hostent = gethostbyname(host)) == NULL)
|
||||
return -2;
|
||||
|
||||
ainfo->ai_servent = getservbyname(port, 0);
|
||||
|
||||
if (ainfo->ai_servent)
|
||||
ainfo->ai_port = ainfo->ai_servent->s_port;
|
||||
else
|
||||
ainfo->ai_port = atol(port);
|
||||
|
||||
memcpy(&ainfo->ai_addr_in.sin_addr,
|
||||
ainfo->ai_hostent->h_addr_list[0],
|
||||
ainfo->ai_hostent->h_length);
|
||||
|
||||
ainfo->ai_protocol = 0;
|
||||
ainfo->ai_socktype = hints->ai_socktype;
|
||||
ainfo->ai_family = ainfo->ai_hostent->h_addrtype;
|
||||
ainfo->ai_addr_in.sin_family = ainfo->ai_family;
|
||||
ainfo->ai_addr_in.sin_port = ainfo->ai_port;
|
||||
ainfo->ai_addr = (struct addrinfo *)&ainfo->ai_addr_in;
|
||||
ainfo->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
|
||||
*info = ainfo;
|
||||
|
||||
if (ainfo->ai_hostent->h_addr_list[1] == NULL) {
|
||||
ainfo->ai_next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ai = ainfo;
|
||||
|
||||
for (p = 1; ainfo->ai_hostent->h_addr_list[p] != NULL; p++) {
|
||||
ai->ai_next = malloc(sizeof(struct addrinfo));
|
||||
memcpy(&ai->ai_next, ainfo, sizeof(struct addrinfo));
|
||||
memcpy(&ai->ai_next->ai_addr_in.sin_addr,
|
||||
ainfo->ai_hostent->h_addr_list[p],
|
||||
ainfo->ai_hostent->h_length);
|
||||
ai->ai_next->ai_addr = (struct addrinfo *)&ai->ai_next->ai_addr_in;
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
|
||||
ai->ai_next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void p_freeaddrinfo(struct addrinfo *info)
|
||||
{
|
||||
struct addrinfo *p, *next;
|
||||
|
||||
p = info;
|
||||
|
||||
while(p != NULL) {
|
||||
next = p->ai_next;
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
|
||||
const char *p_gai_strerror(int ret)
|
||||
{
|
||||
switch(ret) {
|
||||
case -1:
|
||||
return "Out of memory";
|
||||
break;
|
||||
|
||||
case -2:
|
||||
return "Address lookup failed";
|
||||
break;
|
||||
|
||||
default:
|
||||
return "Unknown error";
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* NO_ADDRINFO */
|
||||
|
||||
int p_open(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
@ -63,7 +154,7 @@ int p_rename(const char *from, const char *to)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* GIT_WIN32 */
|
||||
|
||||
int p_read(git_file fd, void *buf, size_t cnt)
|
||||
{
|
||||
|
37
src/posix.h
37
src/posix.h
@ -83,6 +83,41 @@ extern int p_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
# include "unix/posix.h"
|
||||
#endif
|
||||
|
||||
#define p_readdir_r(d,e,r) readdir_r(d,e,r)
|
||||
#ifdef NO_READDIR_R
|
||||
# include <dirent.h>
|
||||
GIT_INLINE(int) p_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
||||
{
|
||||
GIT_UNUSED(entry);
|
||||
*result = readdir(dirp);
|
||||
return 0;
|
||||
}
|
||||
#else /* NO_READDIR_R */
|
||||
# define p_readdir_r(d,e,r) readdir_r(d,e,r)
|
||||
#endif
|
||||
|
||||
#ifdef NO_ADDRINFO
|
||||
# include <netdb.h>
|
||||
struct addrinfo {
|
||||
struct hostent *ai_hostent;
|
||||
struct servent *ai_servent;
|
||||
struct sockaddr_in ai_addr_in;
|
||||
struct sockaddr *ai_addr;
|
||||
size_t ai_addrlen;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
long ai_port;
|
||||
struct addrinfo *ai_next;
|
||||
};
|
||||
|
||||
extern int p_getaddrinfo(const char *host, const char *port,
|
||||
struct addrinfo *hints, struct addrinfo **info);
|
||||
extern void p_freeaddrinfo(struct addrinfo *info);
|
||||
extern const char *p_gai_strerror(int ret);
|
||||
#else
|
||||
# define p_getaddrinfo(a, b, c, d) getaddrinfo(a, b, c, d)
|
||||
# define p_freeaddrinfo(a) freeaddrinfo(a)
|
||||
# define p_gai_strerror(c) gai_strerror(c)
|
||||
#endif /* NO_ADDRINFO */
|
||||
|
||||
#endif
|
||||
|
48
src/reflog.c
48
src/reflog.c
@ -269,18 +269,50 @@ cleanup:
|
||||
|
||||
int git_reflog_rename(git_reference *ref, const char *new_name)
|
||||
{
|
||||
int error;
|
||||
int error = -1, fd;
|
||||
git_buf old_path = GIT_BUF_INIT;
|
||||
git_buf new_path = GIT_BUF_INIT;
|
||||
git_buf temp_path = GIT_BUF_INIT;
|
||||
|
||||
if (!git_buf_join_n(&old_path, '/', 3, ref->owner->path_repository,
|
||||
GIT_REFLOG_DIR, ref->name) &&
|
||||
!git_buf_join_n(&new_path, '/', 3, ref->owner->path_repository,
|
||||
GIT_REFLOG_DIR, new_name))
|
||||
error = p_rename(git_buf_cstr(&old_path), git_buf_cstr(&new_path));
|
||||
else
|
||||
error = -1;
|
||||
assert(ref && new_name);
|
||||
|
||||
if (git_buf_joinpath(&temp_path, ref->owner->path_repository, GIT_REFLOG_DIR) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), ref->name) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), new_name) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* Move the reflog to a temporary place. This two-phase renaming is required
|
||||
* in order to cope with funny renaming use cases when one tries to move a reference
|
||||
* to a partially colliding namespace:
|
||||
* - a/b -> a/b/c
|
||||
* - a/b/c/d -> a/b/c
|
||||
*/
|
||||
if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0)
|
||||
goto cleanup;
|
||||
p_close(fd);
|
||||
|
||||
if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_path_isdir(git_buf_cstr(&new_path)) &&
|
||||
(git_futils_rmdir_r(git_buf_cstr(&new_path), GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0))
|
||||
goto cleanup;
|
||||
|
||||
if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = p_rename(git_buf_cstr(&temp_path), git_buf_cstr(&new_path));
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&temp_path);
|
||||
git_buf_free(&old_path);
|
||||
git_buf_free(&new_path);
|
||||
|
||||
|
142
src/refs.c
142
src/refs.c
@ -11,6 +11,7 @@
|
||||
#include "fileops.h"
|
||||
#include "pack.h"
|
||||
#include "reflog.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <git2/tag.h>
|
||||
#include <git2/object.h>
|
||||
@ -1396,6 +1397,9 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
|
||||
head_target = git_reference_target(head);
|
||||
|
||||
if (head_target && !strcmp(head_target, ref->name)) {
|
||||
git_reference_free(head);
|
||||
head = NULL;
|
||||
|
||||
if (git_reference_create_symbolic(&head, ref->owner, "HEAD", new_name, 1) < 0) {
|
||||
giterr_set(GITERR_REFERENCE,
|
||||
"Failed to update HEAD after renaming reference");
|
||||
@ -1404,18 +1408,11 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename the reflog file.
|
||||
* Rename the reflog file, if it exists.
|
||||
*/
|
||||
if (git_buf_join_n(&aux_path, '/', 3, ref->owner->path_repository, GIT_REFLOG_DIR, ref->name) < 0)
|
||||
if ((git_reference_has_log(ref)) && (git_reflog_rename(ref, new_name) < 0))
|
||||
goto cleanup;
|
||||
|
||||
if (git_path_exists(aux_path.ptr) == true) {
|
||||
if (git_reflog_rename(ref, new_name) < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the name of the reference given by the user.
|
||||
*/
|
||||
@ -1764,3 +1761,130 @@ int git_reference__update(git_repository *repo, const git_oid *oid, const char *
|
||||
git_reference_free(ref);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct glob_cb_data {
|
||||
const char *glob;
|
||||
int (*callback)(const char *, void *);
|
||||
void *payload;
|
||||
};
|
||||
|
||||
static int fromglob_cb(const char *reference_name, void *payload)
|
||||
{
|
||||
struct glob_cb_data *data = (struct glob_cb_data *)payload;
|
||||
|
||||
if (!p_fnmatch(data->glob, reference_name, 0))
|
||||
return data->callback(reference_name, data->payload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_reference_foreach_glob(
|
||||
git_repository *repo,
|
||||
const char *glob,
|
||||
unsigned int list_flags,
|
||||
int (*callback)(
|
||||
const char *reference_name,
|
||||
void *payload),
|
||||
void *payload)
|
||||
{
|
||||
struct glob_cb_data data;
|
||||
|
||||
assert(repo && glob && callback);
|
||||
|
||||
data.glob = glob;
|
||||
data.callback = callback;
|
||||
data.payload = payload;
|
||||
|
||||
return git_reference_foreach(
|
||||
repo, list_flags, fromglob_cb, &data);
|
||||
}
|
||||
|
||||
int git_reference_has_log(
|
||||
git_reference *ref)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
int result;
|
||||
|
||||
assert(ref);
|
||||
|
||||
if (git_buf_join_n(&path, '/', 3, ref->owner->path_repository, GIT_REFLOG_DIR, ref->name) < 0)
|
||||
return -1;
|
||||
|
||||
result = git_path_isfile(git_buf_cstr(&path));
|
||||
git_buf_free(&path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//TODO: How about also taking care of local tracking branches?
|
||||
//cf. http://alblue.bandlem.com/2011/07/git-tip-of-week-tracking-branches.html
|
||||
int git_reference_remote_tracking_from_branch(
|
||||
git_reference **tracking_ref,
|
||||
git_reference *branch_ref)
|
||||
{
|
||||
git_config *config = NULL;
|
||||
const char *name, *remote, *merge;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int error = -1;
|
||||
|
||||
assert(tracking_ref && branch_ref);
|
||||
|
||||
name = git_reference_name(branch_ref);
|
||||
|
||||
if (git__prefixcmp(name, GIT_REFS_HEADS_DIR)) {
|
||||
giterr_set(
|
||||
GITERR_INVALID,
|
||||
"Failed to retrieve tracking reference - '%s' is not a branch.",
|
||||
name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_repository_config(&config, branch_ref->owner) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_buf_printf(
|
||||
&buf,
|
||||
"branch.%s.remote",
|
||||
name + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((error = git_config_get_string(&remote, config, git_buf_cstr(&buf))) < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = -1;
|
||||
|
||||
git_buf_clear(&buf);
|
||||
|
||||
//TODO: Is it ok to fail when no merge target is found?
|
||||
if (git_buf_printf(
|
||||
&buf,
|
||||
"branch.%s.merge",
|
||||
name + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_config_get_string(&merge, config, git_buf_cstr(&buf)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
//TODO: Should we test this?
|
||||
if (git__prefixcmp(merge, GIT_REFS_HEADS_DIR))
|
||||
goto cleanup;
|
||||
|
||||
git_buf_clear(&buf);
|
||||
|
||||
if (git_buf_printf(
|
||||
&buf,
|
||||
"refs/remotes/%s/%s",
|
||||
remote,
|
||||
merge + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = git_reference_lookup(
|
||||
tracking_ref,
|
||||
branch_ref->owner,
|
||||
git_buf_cstr(&buf));
|
||||
|
||||
cleanup:
|
||||
git_config_free(config);
|
||||
git_buf_free(&buf);
|
||||
return error;
|
||||
}
|
||||
|
139
src/repository.c
139
src/repository.c
@ -602,14 +602,10 @@ void git_repository_set_index(git_repository *repo, git_index *index)
|
||||
GIT_REFCOUNT_INC(index);
|
||||
}
|
||||
|
||||
static int check_repositoryformatversion(git_repository *repo)
|
||||
static int check_repositoryformatversion(git_config *config)
|
||||
{
|
||||
git_config *config;
|
||||
int version;
|
||||
|
||||
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_config_get_int32(&version, config, "core.repositoryformatversion") < 0)
|
||||
return -1;
|
||||
|
||||
@ -623,26 +619,6 @@ static int check_repositoryformatversion(git_repository *repo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int repo_init_reinit(git_repository **repo_out, const char *repository_path, int is_bare)
|
||||
{
|
||||
git_repository *repo = NULL;
|
||||
|
||||
GIT_UNUSED(is_bare);
|
||||
|
||||
if (git_repository_open(&repo, repository_path) < 0)
|
||||
return -1;
|
||||
|
||||
if (check_repositoryformatversion(repo) < 0) {
|
||||
git_repository_free(repo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: reinitialize the templates */
|
||||
|
||||
*repo_out = repo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int repo_init_createhead(const char *git_dir)
|
||||
{
|
||||
git_buf ref_path = GIT_BUF_INIT;
|
||||
@ -717,6 +693,12 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_reinit && check_repositoryformatversion(config) < 0) {
|
||||
git_buf_free(&cfg_path);
|
||||
git_config_free(config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SET_REPO_CONFIG(bool, "core.bare", is_bare);
|
||||
SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
|
||||
SET_REPO_CONFIG(bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
|
||||
@ -759,15 +741,24 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
|
||||
#define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n"
|
||||
|
||||
static int repo_write_template(
|
||||
const char *git_dir, const char *file, mode_t mode, const char *content)
|
||||
const char *git_dir,
|
||||
bool allow_overwrite,
|
||||
const char *file,
|
||||
mode_t mode,
|
||||
const char *content)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
int fd, error = 0;
|
||||
int fd, error = 0, flags;
|
||||
|
||||
if (git_buf_joinpath(&path, git_dir, file) < 0)
|
||||
return -1;
|
||||
|
||||
fd = p_open(git_buf_cstr(&path), O_WRONLY | O_CREAT | O_EXCL, mode);
|
||||
if (allow_overwrite)
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
else
|
||||
flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
|
||||
fd = p_open(git_buf_cstr(&path), flags, mode);
|
||||
|
||||
if (fd >= 0) {
|
||||
error = p_write(fd, content, strlen(content));
|
||||
@ -829,7 +820,7 @@ static int repo_init_structure(const char *git_dir, int is_bare)
|
||||
/* Make template files as needed */
|
||||
for (i = 0; tmpl[i].file != NULL; ++i) {
|
||||
if (repo_write_template(
|
||||
git_dir, tmpl[i].file, tmpl[i].mode, tmpl[i].content) < 0)
|
||||
git_dir, false, tmpl[i].file, tmpl[i].mode, tmpl[i].content) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -850,21 +841,18 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
|
||||
is_reinit = git_path_isdir(repository_path.ptr) && valid_repository_path(&repository_path);
|
||||
|
||||
if (is_reinit) {
|
||||
if (repo_init_reinit(repo_out, repository_path.ptr, is_bare) < 0)
|
||||
/* TODO: reinitialize the templates */
|
||||
|
||||
if (repo_init_config(repository_path.ptr, is_bare, is_reinit) < 0)
|
||||
goto cleanup;
|
||||
|
||||
result = repo_init_config(repository_path.ptr, is_bare, is_reinit);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
|
||||
} else if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
|
||||
repo_init_config(repository_path.ptr, is_bare, is_reinit) < 0 ||
|
||||
repo_init_createhead(repository_path.ptr) < 0 ||
|
||||
git_repository_open(repo_out, repository_path.ptr) < 0) {
|
||||
repo_init_createhead(repository_path.ptr) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
result = git_repository_open(repo_out, repository_path.ptr);
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&repository_path);
|
||||
@ -964,8 +952,47 @@ const char *git_repository_workdir(git_repository *repo)
|
||||
return repo->workdir;
|
||||
}
|
||||
|
||||
int git_repository_set_workdir(git_repository *repo, const char *workdir)
|
||||
static int write_gitlink(
|
||||
const char *in_dir, const char *to_repo)
|
||||
{
|
||||
int error;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
struct stat st;
|
||||
|
||||
if (git_path_dirname_r(&buf, to_repo) < 0 ||
|
||||
git_path_to_dir(&buf) < 0)
|
||||
return -1;
|
||||
|
||||
/* don't write gitlink to natural workdir */
|
||||
if (git__suffixcmp(to_repo, "/" DOT_GIT "/") == 0 &&
|
||||
strcmp(in_dir, buf.ptr) == 0)
|
||||
return GIT_PASSTHROUGH;
|
||||
|
||||
if (git_buf_joinpath(&buf, in_dir, DOT_GIT) < 0)
|
||||
return -1;
|
||||
|
||||
if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
|
||||
giterr_set(GITERR_REPOSITORY,
|
||||
"Cannot overwrite gitlink file into path '%s'", in_dir);
|
||||
return GIT_EEXISTS;
|
||||
}
|
||||
|
||||
git_buf_clear(&buf);
|
||||
|
||||
if (git_buf_printf(&buf, "%s %s", GIT_FILE_CONTENT_PREFIX, to_repo) < 0)
|
||||
return -1;
|
||||
|
||||
error = repo_write_template(in_dir, true, DOT_GIT, 0644, buf.ptr);
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_repository_set_workdir(
|
||||
git_repository *repo, const char *workdir, int update_gitlink)
|
||||
{
|
||||
int error = 0;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
assert(repo && workdir);
|
||||
@ -973,11 +1000,37 @@ int git_repository_set_workdir(git_repository *repo, const char *workdir)
|
||||
if (git_path_prettify_dir(&path, workdir, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
git__free(repo->workdir);
|
||||
if (repo->workdir && strcmp(repo->workdir, path.ptr) == 0)
|
||||
return 0;
|
||||
|
||||
repo->workdir = git_buf_detach(&path);
|
||||
repo->is_bare = 0;
|
||||
return 0;
|
||||
if (update_gitlink) {
|
||||
git_config *config;
|
||||
|
||||
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||
return -1;
|
||||
|
||||
error = write_gitlink(path.ptr, git_repository_path(repo));
|
||||
|
||||
/* passthrough error means gitlink is unnecessary */
|
||||
if (error == GIT_PASSTHROUGH)
|
||||
error = git_config_delete(config, "core.worktree");
|
||||
else if (!error)
|
||||
error = git_config_set_string(config, "core.worktree", path.ptr);
|
||||
|
||||
if (!error)
|
||||
error = git_config_set_bool(config, "core.bare", false);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
char *old_workdir = repo->workdir;
|
||||
|
||||
repo->workdir = git_buf_detach(&path);
|
||||
repo->is_bare = 0;
|
||||
|
||||
git__free(old_workdir);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_repository_is_bare(git_repository *repo)
|
||||
|
1194
src/revparse.c
1194
src/revparse.c
File diff suppressed because it is too large
Load Diff
@ -188,7 +188,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
|
||||
const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1;
|
||||
unsigned char *buffer = raw->data;
|
||||
unsigned char *buffer_end = buffer + raw->len;
|
||||
unsigned char *parents_start;
|
||||
unsigned char *parents_start, *committer_start;
|
||||
int i, parents = 0;
|
||||
int commit_time;
|
||||
|
||||
@ -219,17 +219,34 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
|
||||
|
||||
commit->out_degree = (unsigned short)parents;
|
||||
|
||||
if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
|
||||
return commit_error(commit, "object is corrupted");
|
||||
|
||||
buffer++;
|
||||
|
||||
if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
|
||||
return commit_error(commit, "object is corrupted");
|
||||
|
||||
if ((buffer = memchr(buffer, '<', buffer_end - buffer)) == NULL ||
|
||||
(buffer = memchr(buffer, '>', buffer_end - buffer)) == NULL)
|
||||
return commit_error(commit, "malformed author information");
|
||||
/* Skip trailing spaces */
|
||||
while (buffer > committer_start && git__isspace(*buffer))
|
||||
buffer--;
|
||||
|
||||
while (*buffer == '>' || git__isspace(*buffer))
|
||||
buffer++;
|
||||
/* Seek for the begining of the pack of digits */
|
||||
while (buffer > committer_start && git__isdigit(*buffer))
|
||||
buffer--;
|
||||
|
||||
if (git__strtol32(&commit_time, (char *)buffer, NULL, 10) < 0)
|
||||
/* Skip potential timezone offset */
|
||||
if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) {
|
||||
buffer--;
|
||||
|
||||
while (buffer > committer_start && git__isspace(*buffer))
|
||||
buffer--;
|
||||
|
||||
while (buffer > committer_start && git__isdigit(*buffer))
|
||||
buffer--;
|
||||
}
|
||||
|
||||
if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
|
||||
return commit_error(commit, "cannot parse commit time");
|
||||
|
||||
commit->time = (time_t)commit_time;
|
||||
@ -540,7 +557,6 @@ static int push_ref(git_revwalk *walk, const char *refname, int hide)
|
||||
|
||||
struct push_cb_data {
|
||||
git_revwalk *walk;
|
||||
const char *glob;
|
||||
int hide;
|
||||
};
|
||||
|
||||
@ -548,10 +564,7 @@ static int push_glob_cb(const char *refname, void *data_)
|
||||
{
|
||||
struct push_cb_data *data = (struct push_cb_data *)data_;
|
||||
|
||||
if (!p_fnmatch(data->glob, refname, 0))
|
||||
return push_ref(data->walk, refname, data->hide);
|
||||
|
||||
return 0;
|
||||
return push_ref(data->walk, refname, data->hide);
|
||||
}
|
||||
|
||||
static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
||||
@ -584,11 +597,10 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
||||
goto on_error;
|
||||
|
||||
data.walk = walk;
|
||||
data.glob = git_buf_cstr(&buf);
|
||||
data.hide = hide;
|
||||
|
||||
if (git_reference_foreach(
|
||||
walk->repo, GIT_REF_LISTALL, push_glob_cb, &data) < 0)
|
||||
if (git_reference_foreach_glob(
|
||||
walk->repo, git_buf_cstr(&buf), GIT_REF_LISTALL, push_glob_cb, &data) < 0)
|
||||
goto on_error;
|
||||
|
||||
regfree(&preg);
|
||||
|
@ -40,7 +40,7 @@ static const char *skip_trailing_spaces(const char *buffer_start, const char *bu
|
||||
|
||||
static int signature_error(const char *msg)
|
||||
{
|
||||
giterr_set(GITERR_INVALID, "Failed to parse signature - %s", msg);
|
||||
giterr_set(GITERR_INVALID, "Failed to process signature - %s", msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -72,9 +72,16 @@ static int process_trimming(const char *input, char **storage, const char *input
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool contains_angle_brackets(const char *input)
|
||||
{
|
||||
if (strchr(input, '<') != NULL)
|
||||
return true;
|
||||
|
||||
return strchr(input, '>') != NULL;
|
||||
}
|
||||
|
||||
int git_signature_new(git_signature **sig_out, const char *name, const char *email, git_time_t time, int offset)
|
||||
{
|
||||
int error;
|
||||
git_signature *p = NULL;
|
||||
|
||||
assert(name && email);
|
||||
@ -84,11 +91,18 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema
|
||||
p = git__calloc(1, sizeof(git_signature));
|
||||
GITERR_CHECK_ALLOC(p);
|
||||
|
||||
if ((error = process_trimming(name, &p->name, name + strlen(name), 1)) < 0 ||
|
||||
(error = process_trimming(email, &p->email, email + strlen(email), 1)) < 0)
|
||||
if (process_trimming(name, &p->name, name + strlen(name), 1) < 0 ||
|
||||
process_trimming(email, &p->email, email + strlen(email), 1) < 0)
|
||||
{
|
||||
git_signature_free(p);
|
||||
return error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (contains_angle_brackets(p->email) ||
|
||||
contains_angle_brackets(p->name))
|
||||
{
|
||||
git_signature_free(p);
|
||||
return signature_error("Neither `name` nor `email` should contain angle brackets chars.");
|
||||
}
|
||||
|
||||
p->when.time = time;
|
||||
|
@ -19,7 +19,7 @@ __KHASH_TYPE(str, const char *, void *);
|
||||
typedef khash_t(str) git_strmap;
|
||||
|
||||
#define GIT__USE_STRMAP \
|
||||
__KHASH_IMPL(str, static inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
|
||||
__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
|
||||
|
||||
#define git_strmap_alloc() kh_init(str)
|
||||
#define git_strmap_free(h) kh_destroy(str, h), h = NULL
|
||||
|
@ -31,7 +31,7 @@ static git_cvar_map _sm_ignore_map[] = {
|
||||
{GIT_CVAR_STRING, "none", GIT_SUBMODULE_IGNORE_NONE}
|
||||
};
|
||||
|
||||
static inline khint_t str_hash_no_trailing_slash(const char *s)
|
||||
static kh_inline khint_t str_hash_no_trailing_slash(const char *s)
|
||||
{
|
||||
khint_t h;
|
||||
|
||||
@ -42,7 +42,7 @@ static inline khint_t str_hash_no_trailing_slash(const char *s)
|
||||
return h;
|
||||
}
|
||||
|
||||
static inline int str_equal_no_trailing_slash(const char *a, const char *b)
|
||||
static kh_inline int str_equal_no_trailing_slash(const char *a, const char *b)
|
||||
{
|
||||
size_t alen = a ? strlen(a) : 0;
|
||||
size_t blen = b ? strlen(b) : 0;
|
||||
@ -55,7 +55,7 @@ static inline int str_equal_no_trailing_slash(const char *a, const char *b)
|
||||
return (alen == blen && strncmp(a, b, alen) == 0);
|
||||
}
|
||||
|
||||
__KHASH_IMPL(str, static inline, const char *, void *, 1, str_hash_no_trailing_slash, str_equal_no_trailing_slash);
|
||||
__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, str_hash_no_trailing_slash, str_equal_no_trailing_slash);
|
||||
|
||||
static git_submodule *submodule_alloc(const char *name)
|
||||
{
|
||||
|
@ -545,6 +545,7 @@ static int http_download_pack(git_transport *transport, git_repository *repo, gi
|
||||
http_parser_settings settings;
|
||||
char buffer[1024];
|
||||
gitno_buffer buf;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
git_indexer_stream *idx = NULL;
|
||||
download_pack_cbdata data;
|
||||
|
||||
@ -555,7 +556,10 @@ static int http_download_pack(git_transport *transport, git_repository *repo, gi
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_indexer_stream_new(&idx, git_repository_path(repo)) < 0)
|
||||
if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0)
|
||||
return -1;
|
||||
|
||||
if (git_indexer_stream_new(&idx, git_buf_cstr(&path)) < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@ -600,6 +604,7 @@ static int http_download_pack(git_transport *transport, git_repository *repo, gi
|
||||
|
||||
on_error:
|
||||
git_indexer_stream_free(idx);
|
||||
git_buf_free(&path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
250
src/tree.c
250
src/tree.c
@ -35,6 +35,22 @@ static int entry_sort_cmp(const void *a, const void *b)
|
||||
entry_b->filename, entry_b->filename_len, git_tree_entry__is_tree(entry_b));
|
||||
}
|
||||
|
||||
static git_tree_entry *alloc_entry(const char *filename)
|
||||
{
|
||||
git_tree_entry *entry = NULL;
|
||||
size_t filename_len = strlen(filename);
|
||||
|
||||
entry = git__malloc(sizeof(git_tree_entry) + filename_len + 1);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
memset(entry, 0x0, sizeof(git_tree_entry));
|
||||
memcpy(entry->filename, filename, filename_len);
|
||||
entry->filename[filename_len] = 0;
|
||||
entry->filename_len = filename_len;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct tree_key_search {
|
||||
const char *filename;
|
||||
@ -76,7 +92,7 @@ static int homing_search_cmp(const void *key, const void *array_member)
|
||||
* ambiguous because of folder vs file sorting, we look linearly
|
||||
* around the area for our target file.
|
||||
*/
|
||||
static int tree_key_search(git_vector *entries, const char *filename)
|
||||
static int tree_key_search(git_vector *entries, const char *filename, size_t filename_len)
|
||||
{
|
||||
struct tree_key_search ksearch;
|
||||
const git_tree_entry *entry;
|
||||
@ -84,7 +100,7 @@ static int tree_key_search(git_vector *entries, const char *filename)
|
||||
int homing, i;
|
||||
|
||||
ksearch.filename = filename;
|
||||
ksearch.filename_len = strlen(filename);
|
||||
ksearch.filename_len = filename_len;
|
||||
|
||||
/* Initial homing search; find an entry on the tree with
|
||||
* the same prefix as the filename we're looking for */
|
||||
@ -100,7 +116,8 @@ static int tree_key_search(git_vector *entries, const char *filename)
|
||||
if (homing_search_cmp(&ksearch, entry) < 0)
|
||||
break;
|
||||
|
||||
if (strcmp(filename, entry->filename) == 0)
|
||||
if (entry->filename_len == filename_len &&
|
||||
memcmp(filename, entry->filename, filename_len) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -112,7 +129,8 @@ static int tree_key_search(git_vector *entries, const char *filename)
|
||||
if (homing_search_cmp(&ksearch, entry) > 0)
|
||||
break;
|
||||
|
||||
if (strcmp(filename, entry->filename) == 0)
|
||||
if (entry->filename_len == filename_len &&
|
||||
memcmp(filename, entry->filename, filename_len) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -120,16 +138,38 @@ static int tree_key_search(git_vector *entries, const char *filename)
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
void git_tree_entry_free(git_tree_entry *entry)
|
||||
{
|
||||
if (entry == NULL)
|
||||
return;
|
||||
|
||||
git__free(entry);
|
||||
}
|
||||
|
||||
git_tree_entry *git_tree_entry_dup(const git_tree_entry *entry)
|
||||
{
|
||||
size_t total_size;
|
||||
git_tree_entry *copy;
|
||||
|
||||
assert(entry);
|
||||
|
||||
total_size = sizeof(git_tree_entry) + entry->filename_len + 1;
|
||||
|
||||
copy = git__malloc(total_size);
|
||||
if (!copy)
|
||||
return NULL;
|
||||
|
||||
memcpy(copy, entry, total_size);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void git_tree__free(git_tree *tree)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < tree->entries.length; ++i) {
|
||||
git_tree_entry *e;
|
||||
e = git_vector_get(&tree->entries, i);
|
||||
|
||||
git__free(e->filename);
|
||||
git__free(e);
|
||||
git_tree_entry *e = git_vector_get(&tree->entries, i);
|
||||
git_tree_entry_free(e);
|
||||
}
|
||||
|
||||
git_vector_free(&tree->entries);
|
||||
@ -179,19 +219,21 @@ int git_tree_entry_to_object(
|
||||
return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
|
||||
}
|
||||
|
||||
const git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
|
||||
static git_tree_entry *entry_fromname(git_tree *tree, const char *name, size_t name_len)
|
||||
{
|
||||
int idx;
|
||||
|
||||
assert(tree && filename);
|
||||
|
||||
idx = tree_key_search(&tree->entries, filename);
|
||||
if (idx == GIT_ENOTFOUND)
|
||||
int idx = tree_key_search(&tree->entries, name, name_len);
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
|
||||
return git_vector_get(&tree->entries, idx);
|
||||
}
|
||||
|
||||
const git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
|
||||
{
|
||||
assert(tree && filename);
|
||||
return entry_fromname(tree, filename, strlen(filename));
|
||||
}
|
||||
|
||||
const git_tree_entry *git_tree_entry_byindex(git_tree *tree, unsigned int idx)
|
||||
{
|
||||
assert(tree);
|
||||
@ -244,28 +286,28 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
|
||||
|
||||
while (buffer < buffer_end) {
|
||||
git_tree_entry *entry;
|
||||
int tmp;
|
||||
int attr;
|
||||
|
||||
entry = git__calloc(1, sizeof(git_tree_entry));
|
||||
GITERR_CHECK_ALLOC(entry);
|
||||
|
||||
if (git_vector_insert(&tree->entries, entry) < 0)
|
||||
return -1;
|
||||
|
||||
if (git__strtol32(&tmp, buffer, &buffer, 8) < 0 ||
|
||||
!buffer || !valid_attributes(tmp))
|
||||
if (git__strtol32(&attr, buffer, &buffer, 8) < 0 ||
|
||||
!buffer || !valid_attributes(attr))
|
||||
return tree_error("Failed to parse tree. Can't parse attributes");
|
||||
|
||||
entry->attr = tmp;
|
||||
|
||||
if (*buffer++ != ' ')
|
||||
return tree_error("Failed to parse tree. Object is corrupted");
|
||||
|
||||
if (memchr(buffer, 0, buffer_end - buffer) == NULL)
|
||||
return tree_error("Failed to parse tree. Object is corrupted");
|
||||
|
||||
entry->filename = git__strdup(buffer);
|
||||
entry->filename_len = strlen(buffer);
|
||||
/** Allocate the entry and store it in the entries vector */
|
||||
{
|
||||
entry = alloc_entry(buffer);
|
||||
GITERR_CHECK_ALLOC(entry);
|
||||
|
||||
if (git_vector_insert(&tree->entries, entry) < 0)
|
||||
return -1;
|
||||
|
||||
entry->attr = attr;
|
||||
}
|
||||
|
||||
while (buffer < buffer_end && *buffer != 0)
|
||||
buffer++;
|
||||
@ -303,16 +345,17 @@ static unsigned int find_next_dir(const char *dirname, git_index *index, unsigne
|
||||
return i;
|
||||
}
|
||||
|
||||
static int append_entry(git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes)
|
||||
static int append_entry(
|
||||
git_treebuilder *bld,
|
||||
const char *filename,
|
||||
const git_oid *id,
|
||||
unsigned int attributes)
|
||||
{
|
||||
git_tree_entry *entry;
|
||||
|
||||
entry = git__calloc(1, sizeof(git_tree_entry));
|
||||
entry = alloc_entry(filename);
|
||||
GITERR_CHECK_ALLOC(entry);
|
||||
|
||||
entry->filename = git__strdup(filename);
|
||||
entry->filename_len = strlen(entry->filename);
|
||||
|
||||
git_oid_cpy(&entry->oid, id);
|
||||
entry->attr = attributes;
|
||||
|
||||
@ -488,7 +531,12 @@ on_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes)
|
||||
int git_treebuilder_insert(
|
||||
const git_tree_entry **entry_out,
|
||||
git_treebuilder *bld,
|
||||
const char *filename,
|
||||
const git_oid *id,
|
||||
unsigned int attributes)
|
||||
{
|
||||
git_tree_entry *entry;
|
||||
int pos;
|
||||
@ -501,30 +549,28 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
|
||||
if (!valid_entry_name(filename))
|
||||
return tree_error("Failed to insert entry. Invalid name for a tree entry");
|
||||
|
||||
pos = tree_key_search(&bld->entries, filename);
|
||||
pos = tree_key_search(&bld->entries, filename, strlen(filename));
|
||||
|
||||
if (pos >= 0) {
|
||||
entry = git_vector_get(&bld->entries, pos);
|
||||
if (entry->removed)
|
||||
entry->removed = 0;
|
||||
} else {
|
||||
entry = git__calloc(1, sizeof(git_tree_entry));
|
||||
entry = alloc_entry(filename);
|
||||
GITERR_CHECK_ALLOC(entry);
|
||||
|
||||
entry->filename = git__strdup(filename);
|
||||
entry->filename_len = strlen(entry->filename);
|
||||
}
|
||||
|
||||
git_oid_cpy(&entry->oid, id);
|
||||
entry->attr = attributes;
|
||||
|
||||
if (pos == GIT_ENOTFOUND) {
|
||||
if (pos < 0) {
|
||||
if (git_vector_insert(&bld->entries, entry) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (entry_out != NULL)
|
||||
if (entry_out != NULL) {
|
||||
*entry_out = entry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -536,7 +582,7 @@ static git_tree_entry *treebuilder_get(git_treebuilder *bld, const char *filenam
|
||||
|
||||
assert(bld && filename);
|
||||
|
||||
idx = tree_key_search(&bld->entries, filename);
|
||||
idx = tree_key_search(&bld->entries, filename, strlen(filename));
|
||||
if (idx < 0)
|
||||
return NULL;
|
||||
|
||||
@ -625,8 +671,7 @@ void git_treebuilder_clear(git_treebuilder *bld)
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *e = bld->entries.contents[i];
|
||||
git__free(e->filename);
|
||||
git__free(e);
|
||||
git_tree_entry_free(e);
|
||||
}
|
||||
|
||||
git_vector_clear(&bld->entries);
|
||||
@ -642,85 +687,78 @@ void git_treebuilder_free(git_treebuilder *bld)
|
||||
git__free(bld);
|
||||
}
|
||||
|
||||
static int tree_frompath(
|
||||
git_tree **parent_out,
|
||||
git_tree *root,
|
||||
git_buf *treeentry_path,
|
||||
size_t offset)
|
||||
static size_t subpath_len(const char *path)
|
||||
{
|
||||
const char *slash_pos = strchr(path, '/');
|
||||
if (slash_pos == NULL)
|
||||
return strlen(path);
|
||||
|
||||
return slash_pos - path;
|
||||
}
|
||||
|
||||
int git_tree_entry_bypath(
|
||||
git_tree_entry **entry_out,
|
||||
git_tree *root,
|
||||
const char *path)
|
||||
{
|
||||
char *slash_pos = NULL;
|
||||
const git_tree_entry* entry;
|
||||
int error = 0;
|
||||
git_tree *subtree;
|
||||
const git_tree_entry *entry;
|
||||
size_t filename_len;
|
||||
|
||||
if (!*(treeentry_path->ptr + offset)) {
|
||||
giterr_set(GITERR_INVALID,
|
||||
"Invalid relative path to a tree entry '%s'.", treeentry_path->ptr);
|
||||
return -1;
|
||||
}
|
||||
/* Find how long is the current path component (i.e.
|
||||
* the filename between two slashes */
|
||||
filename_len = subpath_len(path);
|
||||
|
||||
slash_pos = (char *)strchr(treeentry_path->ptr + offset, '/');
|
||||
|
||||
if (slash_pos == NULL)
|
||||
return git_tree_lookup(
|
||||
parent_out,
|
||||
root->object.repo,
|
||||
git_object_id((const git_object *)root)
|
||||
);
|
||||
|
||||
if (slash_pos == treeentry_path->ptr + offset) {
|
||||
giterr_set(GITERR_INVALID,
|
||||
"Invalid relative path to a tree entry '%s'.", treeentry_path->ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*slash_pos = '\0';
|
||||
|
||||
entry = git_tree_entry_byname(root, treeentry_path->ptr + offset);
|
||||
|
||||
if (slash_pos != NULL)
|
||||
*slash_pos = '/';
|
||||
|
||||
if (entry == NULL) {
|
||||
giterr_set(GITERR_TREE,
|
||||
"No tree entry can be found from "
|
||||
"the given tree and relative path '%s'.", treeentry_path->ptr);
|
||||
if (filename_len == 0) {
|
||||
giterr_set(GITERR_TREE, "Invalid tree path given");
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
entry = entry_fromname(root, path, filename_len);
|
||||
|
||||
if (entry == NULL) {
|
||||
giterr_set(GITERR_TREE,
|
||||
"The path '%s' does not exist in the given tree", path);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
switch (path[filename_len]) {
|
||||
case '/':
|
||||
/* If there are more components in the path...
|
||||
* then this entry *must* be a tree */
|
||||
if (!git_tree_entry__is_tree(entry)) {
|
||||
giterr_set(GITERR_TREE,
|
||||
"The path '%s' does not exist in the given tree", path);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
/* If there's only a slash left in the path, we
|
||||
* return the current entry; otherwise, we keep
|
||||
* walking down the path */
|
||||
if (path[filename_len + 1] != '\0')
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
/* If there are no more components in the path, return
|
||||
* this entry */
|
||||
*entry_out = git_tree_entry_dup(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
|
||||
return error;
|
||||
return -1;
|
||||
|
||||
error = tree_frompath(
|
||||
parent_out,
|
||||
error = git_tree_entry_bypath(
|
||||
entry_out,
|
||||
subtree,
|
||||
treeentry_path,
|
||||
(slash_pos - treeentry_path->ptr) + 1
|
||||
path + filename_len + 1
|
||||
);
|
||||
|
||||
git_tree_free(subtree);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tree_get_subtree(
|
||||
git_tree **subtree,
|
||||
git_tree *root,
|
||||
const char *subtree_path)
|
||||
{
|
||||
int error;
|
||||
git_buf buffer = GIT_BUF_INIT;
|
||||
|
||||
assert(subtree && root && subtree_path);
|
||||
|
||||
if ((error = git_buf_sets(&buffer, subtree_path)) == 0)
|
||||
error = tree_frompath(subtree, root, &buffer, 0);
|
||||
|
||||
git_buf_free(&buffer);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int tree_walk_post(
|
||||
git_tree *tree,
|
||||
git_treewalk_cb callback,
|
||||
|
@ -13,11 +13,11 @@
|
||||
#include "vector.h"
|
||||
|
||||
struct git_tree_entry {
|
||||
unsigned int attr;
|
||||
char *filename;
|
||||
uint16_t removed;
|
||||
uint16_t attr;
|
||||
git_oid oid;
|
||||
size_t filename_len;
|
||||
int removed;
|
||||
char filename[1];
|
||||
};
|
||||
|
||||
struct git_tree {
|
||||
|
@ -33,6 +33,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
|
||||
mflag = MAP_PRIVATE;
|
||||
|
||||
out->data = mmap(NULL, len, mprot, mflag, fd, offset);
|
||||
|
||||
if (!out->data || out->data == MAP_FAILED) {
|
||||
giterr_set(GITERR_OS, "Failed to mmap. Could not write data");
|
||||
return -1;
|
||||
@ -47,6 +48,7 @@ int p_munmap(git_map *map)
|
||||
{
|
||||
assert(map != NULL);
|
||||
munmap(map->data, map->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef INCLUDE_posix__w32_h__
|
||||
#define INCLUDE_posix__w32_h__
|
||||
|
||||
#ifndef __sun
|
||||
#if !defined(__sun) && !defined(__amigaos4__)
|
||||
# include <fnmatch.h>
|
||||
# define p_fnmatch(p, s, f) fnmatch(p, s, f)
|
||||
#else
|
||||
|
10
src/util.h
10
src/util.h
@ -204,16 +204,14 @@ GIT_INLINE(bool) git__isalpha(int c)
|
||||
return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
|
||||
}
|
||||
|
||||
GIT_INLINE(bool) git__isspace(int c)
|
||||
GIT_INLINE(bool) git__isdigit(int c)
|
||||
{
|
||||
return (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == '\v');
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git__time_cmp(const git_time *a, const git_time *b)
|
||||
GIT_INLINE(bool) git__isspace(int c)
|
||||
{
|
||||
/* Adjust for time zones. Times are in seconds, offsets are in minutes. */
|
||||
git_time_t adjusted_a = a->time + ((b->offset - a->offset) * 60);
|
||||
return (int)(adjusted_a - b->time);
|
||||
return (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == '\v' || c == 0x85 /* Unicode CR+LF */);
|
||||
}
|
||||
|
||||
GIT_INLINE(bool) git__iswildcard(int c)
|
||||
|
@ -238,7 +238,7 @@ int p_open(const char *path, int flags, ...)
|
||||
va_list arg_list;
|
||||
|
||||
va_start(arg_list, flags);
|
||||
mode = va_arg(arg_list, mode_t);
|
||||
mode = (mode_t)va_arg(arg_list, int);
|
||||
va_end(arg_list);
|
||||
}
|
||||
|
||||
|
57
tests-clar/commit/parent.c
Normal file
57
tests-clar/commit/parent.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
static git_repository *_repo;
|
||||
static git_commit *commit;
|
||||
|
||||
void test_commit_parent__initialize(void)
|
||||
{
|
||||
git_oid oid;
|
||||
|
||||
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
|
||||
|
||||
git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
cl_git_pass(git_commit_lookup(&commit, _repo, &oid));
|
||||
}
|
||||
|
||||
void test_commit_parent__cleanup(void)
|
||||
{
|
||||
git_commit_free(commit);
|
||||
git_repository_free(_repo);
|
||||
}
|
||||
|
||||
static void assert_nth_gen_parent(unsigned int gen, const char *expected_oid)
|
||||
{
|
||||
git_commit *parent = NULL;
|
||||
int error;
|
||||
|
||||
error = git_commit_nth_gen_ancestor(&parent, commit, gen);
|
||||
|
||||
if (expected_oid != NULL) {
|
||||
cl_assert_equal_i(0, error);
|
||||
cl_assert_equal_i(0, git_oid_streq(git_commit_id(parent), expected_oid));
|
||||
} else
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, error);
|
||||
|
||||
git_commit_free(parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* $ git show be35~0
|
||||
* commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644
|
||||
*
|
||||
* $ git show be35~1
|
||||
* commit 9fd738e8f7967c078dceed8190330fc8648ee56a
|
||||
*
|
||||
* $ git show be35~3
|
||||
* commit 5b5b025afb0b4c913b4c338a42934a3863bf3644
|
||||
*
|
||||
* $ git show be35~42
|
||||
* fatal: ambiguous argument 'be35~42': unknown revision or path not in the working tree.
|
||||
*/
|
||||
void test_commit_parent__can_retrieve_nth_generation_parent(void)
|
||||
{
|
||||
assert_nth_gen_parent(0, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
assert_nth_gen_parent(1, "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
assert_nth_gen_parent(3, "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
assert_nth_gen_parent(42, NULL);
|
||||
}
|
@ -13,17 +13,39 @@ static int try_build_signature(const char *name, const char *email, git_time_t t
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void test_commit_signature__create_trim(void)
|
||||
static void assert_name_and_email(
|
||||
const char *expected_name,
|
||||
const char *expected_email,
|
||||
const char *name,
|
||||
const char *email)
|
||||
{
|
||||
// creating a signature trims leading and trailing spaces
|
||||
git_signature *sign;
|
||||
cl_git_pass(git_signature_new(&sign, " nulltoken ", " emeric.fermas@gmail.com ", 1234567890, 60));
|
||||
cl_assert(strcmp(sign->name, "nulltoken") == 0);
|
||||
cl_assert(strcmp(sign->email, "emeric.fermas@gmail.com") == 0);
|
||||
git_signature_free((git_signature *)sign);
|
||||
git_signature *sign;
|
||||
|
||||
cl_git_pass(git_signature_new(&sign, name, email, 1234567890, 60));
|
||||
cl_assert_equal_s(expected_name, sign->name);
|
||||
cl_assert_equal_s(expected_email, sign->email);
|
||||
|
||||
git_signature_free(sign);
|
||||
}
|
||||
|
||||
void test_commit_signature__leading_and_trailing_spaces_are_trimmed(void)
|
||||
{
|
||||
assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " nulltoken ", " emeric.fermas@gmail.com ");
|
||||
}
|
||||
|
||||
void test_commit_signature__angle_brackets_in_names_are_not_supported(void)
|
||||
{
|
||||
cl_git_fail(try_build_signature("<Phil Haack", "phil@haack", 1234567890, 60));
|
||||
cl_git_fail(try_build_signature("Phil>Haack", "phil@haack", 1234567890, 60));
|
||||
cl_git_fail(try_build_signature("<Phil Haack>", "phil@haack", 1234567890, 60));
|
||||
}
|
||||
|
||||
void test_commit_signature__angle_brackets_in_email_are_not_supported(void)
|
||||
{
|
||||
cl_git_fail(try_build_signature("Phil Haack", ">phil@haack", 1234567890, 60));
|
||||
cl_git_fail(try_build_signature("Phil Haack", "phil@>haack", 1234567890, 60));
|
||||
cl_git_fail(try_build_signature("Phil Haack", "<phil@haack>", 1234567890, 60));
|
||||
}
|
||||
|
||||
void test_commit_signature__create_empties(void)
|
||||
{
|
||||
@ -39,21 +61,13 @@ void test_commit_signature__create_empties(void)
|
||||
void test_commit_signature__create_one_char(void)
|
||||
{
|
||||
// creating a one character signature
|
||||
git_signature *sign;
|
||||
cl_git_pass(git_signature_new(&sign, "x", "foo@bar.baz", 1234567890, 60));
|
||||
cl_assert(strcmp(sign->name, "x") == 0);
|
||||
cl_assert(strcmp(sign->email, "foo@bar.baz") == 0);
|
||||
git_signature_free((git_signature *)sign);
|
||||
assert_name_and_email("x", "foo@bar.baz", "x", "foo@bar.baz");
|
||||
}
|
||||
|
||||
void test_commit_signature__create_two_char(void)
|
||||
{
|
||||
// creating a two character signature
|
||||
git_signature *sign;
|
||||
cl_git_pass(git_signature_new(&sign, "xx", "x@y.z", 1234567890, 60));
|
||||
cl_assert(strcmp(sign->name, "xx") == 0);
|
||||
cl_assert(strcmp(sign->email, "x@y.z") == 0);
|
||||
git_signature_free((git_signature *)sign);
|
||||
assert_name_and_email("xx", "foo@bar.baz", "xx", "foo@bar.baz");
|
||||
}
|
||||
|
||||
void test_commit_signature__create_zero_char(void)
|
||||
|
@ -191,6 +191,81 @@ void test_config_read__escaping_quotes(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
static int count_cfg_entries(
|
||||
const char *var_name, const char *value, void *payload)
|
||||
{
|
||||
int *count = payload;
|
||||
GIT_UNUSED(var_name);
|
||||
GIT_UNUSED(value);
|
||||
(*count)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cfg_callback_countdown(
|
||||
const char *var_name, const char *value, void *payload)
|
||||
{
|
||||
int *count = payload;
|
||||
GIT_UNUSED(var_name);
|
||||
GIT_UNUSED(value);
|
||||
(*count)--;
|
||||
if (*count == 0)
|
||||
return -100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_config_read__foreach(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
int count, ret;
|
||||
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(git_config_foreach(cfg, count_cfg_entries, &count));
|
||||
cl_assert_equal_i(5, count);
|
||||
|
||||
count = 3;
|
||||
cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count));
|
||||
cl_assert_equal_i(-100, ret);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__foreach_match(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
int count;
|
||||
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(
|
||||
git_config_foreach_match(cfg, "core.*", count_cfg_entries, &count));
|
||||
cl_assert_equal_i(3, count);
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(
|
||||
git_config_foreach_match(cfg, "remote\\.ab.*", count_cfg_entries, &count));
|
||||
cl_assert_equal_i(2, count);
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(
|
||||
git_config_foreach_match(cfg, ".*url$", count_cfg_entries, &count));
|
||||
cl_assert_equal_i(2, count);
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(
|
||||
git_config_foreach_match(cfg, ".*dummy.*", count_cfg_entries, &count));
|
||||
cl_assert_equal_i(2, count);
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(
|
||||
git_config_foreach_match(cfg, ".*nomatch.*", count_cfg_entries, &count));
|
||||
cl_assert_equal_i(0, count);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
BEGIN_TEST(config10, "a repo's config overrides the global config")
|
||||
|
@ -611,3 +611,50 @@ void test_core_buffer__11(void)
|
||||
|
||||
git_buf_free(&a);
|
||||
}
|
||||
|
||||
void test_core_buffer__rfind_variants(void)
|
||||
{
|
||||
git_buf a = GIT_BUF_INIT;
|
||||
ssize_t len;
|
||||
|
||||
cl_git_pass(git_buf_sets(&a, "/this/is/it/"));
|
||||
|
||||
len = (ssize_t)git_buf_len(&a);
|
||||
|
||||
cl_assert(git_buf_rfind(&a, '/') == len - 1);
|
||||
cl_assert(git_buf_rfind_next(&a, '/') == len - 4);
|
||||
|
||||
cl_assert(git_buf_rfind(&a, 'i') == len - 3);
|
||||
cl_assert(git_buf_rfind_next(&a, 'i') == len - 3);
|
||||
|
||||
cl_assert(git_buf_rfind(&a, 'h') == 2);
|
||||
cl_assert(git_buf_rfind_next(&a, 'h') == 2);
|
||||
|
||||
cl_assert(git_buf_rfind(&a, 'q') == -1);
|
||||
cl_assert(git_buf_rfind_next(&a, 'q') == -1);
|
||||
|
||||
git_buf_free(&a);
|
||||
}
|
||||
|
||||
void test_core_buffer__puts_escaped(void)
|
||||
{
|
||||
git_buf a = GIT_BUF_INIT;
|
||||
|
||||
git_buf_clear(&a);
|
||||
cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "", ""));
|
||||
cl_assert_equal_s("this is a test", a.ptr);
|
||||
|
||||
git_buf_clear(&a);
|
||||
cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "t", "\\"));
|
||||
cl_assert_equal_s("\\this is a \\tes\\t", a.ptr);
|
||||
|
||||
git_buf_clear(&a);
|
||||
cl_git_pass(git_buf_puts_escaped(&a, "this is a test", "i ", "__"));
|
||||
cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr);
|
||||
|
||||
git_buf_clear(&a);
|
||||
cl_git_pass(git_buf_puts_escape_regex(&a, "^match\\s*[A-Z]+.*"));
|
||||
cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr);
|
||||
|
||||
git_buf_free(&a);
|
||||
}
|
||||
|
@ -418,3 +418,54 @@ void test_core_path__13_cannot_prettify_a_non_existing_file(void)
|
||||
|
||||
git_buf_free(&p);
|
||||
}
|
||||
|
||||
void test_core_path__14_apply_relative(void)
|
||||
{
|
||||
git_buf p = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_buf_sets(&p, "/this/is/a/base"));
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../test"));
|
||||
cl_assert_equal_s("/this/is/a/test", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../the/./end"));
|
||||
cl_assert_equal_s("/this/is/the/end", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "./of/this/../the/string"));
|
||||
cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../.."));
|
||||
cl_assert_equal_s("/this/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../"));
|
||||
cl_assert_equal_s("/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../.."));
|
||||
cl_assert_equal_s("/", p.ptr);
|
||||
|
||||
|
||||
cl_git_pass(git_buf_sets(&p, "d:/another/test"));
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../.."));
|
||||
cl_assert_equal_s("d:/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/."));
|
||||
cl_assert_equal_s("d:/from/here/and/back/", p.ptr);
|
||||
|
||||
|
||||
cl_git_pass(git_buf_sets(&p, "https://my.url.com/test.git"));
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../another.git"));
|
||||
cl_assert_equal_s("https://my.url.com/another.git", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../full/path/url.patch"));
|
||||
cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, ".."));
|
||||
cl_assert_equal_s("https://my.url.com/full/path/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../"));
|
||||
cl_assert_equal_s("https://", p.ptr);
|
||||
|
||||
git_buf_free(&p);
|
||||
}
|
||||
|
@ -14,13 +14,13 @@ void test_diff_blob__initialize(void)
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.context_lines = 1;
|
||||
opts.interhunk_lines = 1;
|
||||
opts.interhunk_lines = 0;
|
||||
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
|
||||
/* tests/resources/attr/root_test4.txt */
|
||||
cl_git_pass(git_oid_fromstrn(&oid, "fe773770c5a6", 12));
|
||||
cl_git_pass(git_blob_lookup_prefix(&d, g_repo, &oid, 6));
|
||||
cl_git_pass(git_oid_fromstrn(&oid, "a0f7217a", 8));
|
||||
cl_git_pass(git_blob_lookup_prefix(&d, g_repo, &oid, 4));
|
||||
|
||||
/* alien.png */
|
||||
cl_git_pass(git_oid_fromstrn(&oid, "edf3dcee", 8));
|
||||
@ -54,6 +54,7 @@ void test_diff_blob__can_compare_text_blobs(void)
|
||||
|
||||
/* Doing the equivalent of a `git diff -U1` on these files */
|
||||
|
||||
/* diff on tests/resources/attr/root_test1 */
|
||||
cl_git_pass(git_diff_blobs(
|
||||
a, b, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
|
||||
@ -67,6 +68,7 @@ void test_diff_blob__can_compare_text_blobs(void)
|
||||
cl_assert(expected.line_adds == 5);
|
||||
cl_assert(expected.line_dels == 0);
|
||||
|
||||
/* diff on tests/resources/attr/root_test2 */
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
cl_git_pass(git_diff_blobs(
|
||||
b, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
@ -81,6 +83,7 @@ void test_diff_blob__can_compare_text_blobs(void)
|
||||
cl_assert(expected.line_adds == 9);
|
||||
cl_assert(expected.line_dels == 3);
|
||||
|
||||
/* diff on tests/resources/attr/root_test3 */
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
cl_git_pass(git_diff_blobs(
|
||||
a, c, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
@ -95,8 +98,6 @@ void test_diff_blob__can_compare_text_blobs(void)
|
||||
cl_assert(expected.line_adds == 12);
|
||||
cl_assert(expected.line_dels == 1);
|
||||
|
||||
opts.context_lines = 1;
|
||||
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
cl_git_pass(git_diff_blobs(
|
||||
c, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
@ -252,3 +253,62 @@ void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void)
|
||||
|
||||
assert_binary_blobs_comparison(expected);
|
||||
}
|
||||
|
||||
/*
|
||||
* $ git diff fe773770 a0f7217
|
||||
* diff --git a/fe773770 b/a0f7217
|
||||
* index fe77377..a0f7217 100644
|
||||
* --- a/fe773770
|
||||
* +++ b/a0f7217
|
||||
* @@ -1,6 +1,6 @@
|
||||
* Here is some stuff at the start
|
||||
*
|
||||
* -This should go in one hunk
|
||||
* +This should go in one hunk (first)
|
||||
*
|
||||
* Some additional lines
|
||||
*
|
||||
* @@ -8,7 +8,7 @@ Down here below the other lines
|
||||
*
|
||||
* With even more at the end
|
||||
*
|
||||
* -Followed by a second hunk of stuff
|
||||
* +Followed by a second hunk of stuff (second)
|
||||
*
|
||||
* That happens down here
|
||||
*/
|
||||
void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
|
||||
{
|
||||
git_blob *old_d;
|
||||
git_oid old_d_oid;
|
||||
|
||||
opts.context_lines = 3;
|
||||
|
||||
/* tests/resources/attr/root_test1 from commit f5b0af1 */
|
||||
cl_git_pass(git_oid_fromstrn(&old_d_oid, "fe773770", 8));
|
||||
cl_git_pass(git_blob_lookup_prefix(&old_d, g_repo, &old_d_oid, 4));
|
||||
|
||||
/* Test with default inter-hunk-context (not set) => default is 0 */
|
||||
cl_git_pass(git_diff_blobs(
|
||||
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
|
||||
cl_assert(expected.hunks == 2);
|
||||
|
||||
/* Test with inter-hunk-context explicitly set to 0 */
|
||||
opts.interhunk_lines = 0;
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
cl_git_pass(git_diff_blobs(
|
||||
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
|
||||
cl_assert(expected.hunks == 2);
|
||||
|
||||
/* Test with inter-hunk-context explicitly set to 1 */
|
||||
opts.interhunk_lines = 1;
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
cl_git_pass(git_diff_blobs(
|
||||
old_d, d, &opts, &expected, diff_file_fn, diff_hunk_fn, diff_line_fn));
|
||||
|
||||
cl_assert(expected.hunks == 1);
|
||||
|
||||
git_blob_free(old_d);
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ static const char *expected_index_oids_0[] = {
|
||||
"45141a79a77842c59a63229403220a4e4be74e3d",
|
||||
"4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d",
|
||||
"108bb4e7fd7b16490dc33ff7d972151e73d7166e",
|
||||
"fe773770c5a6cc7185580c9204b1ff18a33ff3fc",
|
||||
"a0f7217ae99f5ac3e88534f5cea267febc5fa85b",
|
||||
"3e42ffc54a663f9401cc25843d6c0e71a33e4249",
|
||||
"45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
|
||||
"45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
|
||||
@ -343,7 +343,7 @@ static const char *expected_index_oids_range[] = {
|
||||
"45141a79a77842c59a63229403220a4e4be74e3d",
|
||||
"4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d",
|
||||
"108bb4e7fd7b16490dc33ff7d972151e73d7166e",
|
||||
"fe773770c5a6cc7185580c9204b1ff18a33ff3fc",
|
||||
"a0f7217ae99f5ac3e88534f5cea267febc5fa85b",
|
||||
};
|
||||
|
||||
void test_diff_iterator__index_range(void)
|
||||
|
@ -107,7 +107,7 @@ void test_network_remotelocal__retrieve_advertised_references(void)
|
||||
|
||||
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
|
||||
|
||||
cl_assert_equal_i(how_many_refs, 21);
|
||||
cl_assert_equal_i(how_many_refs, 22);
|
||||
}
|
||||
|
||||
void test_network_remotelocal__retrieve_advertised_references_from_spaced_repository(void)
|
||||
@ -121,7 +121,7 @@ void test_network_remotelocal__retrieve_advertised_references_from_spaced_reposi
|
||||
|
||||
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
|
||||
|
||||
cl_assert_equal_i(how_many_refs, 21);
|
||||
cl_assert_equal_i(how_many_refs, 22);
|
||||
|
||||
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
|
||||
remote = NULL;
|
||||
|
@ -23,6 +23,8 @@ static void assert_note_equal(git_note *note, char *message, git_oid *note_oid)
|
||||
|
||||
cl_git_pass(git_blob_lookup(&blob, _repo, note_oid));
|
||||
cl_assert_equal_s(git_note_message(note), (const char *)git_blob_rawcontent(blob));
|
||||
|
||||
git_blob_free(blob);
|
||||
}
|
||||
|
||||
static void create_note(git_oid *note_oid, const char *canonical_namespace, const char *target_sha, const char *message)
|
||||
|
@ -1,15 +1,14 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
static git_repository *repo;
|
||||
const char *tree_with_subtrees_oid = "ae90f12eea699729ed24555e40b9fd669da12a12";
|
||||
static git_tree *tree;
|
||||
|
||||
void test_object_tree_frompath__initialize(void)
|
||||
{
|
||||
git_oid id;
|
||||
const char *tree_with_subtrees_oid = "ae90f12eea699729ed24555e40b9fd669da12a12";
|
||||
|
||||
cl_fixture_sandbox("testrepo.git");
|
||||
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
|
||||
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
|
||||
cl_assert(repo != NULL);
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, tree_with_subtrees_oid));
|
||||
@ -21,61 +20,46 @@ void test_object_tree_frompath__cleanup(void)
|
||||
{
|
||||
git_tree_free(tree);
|
||||
git_repository_free(repo);
|
||||
cl_fixture_cleanup("testrepo.git");
|
||||
}
|
||||
|
||||
static void assert_tree_from_path(git_tree *root, const char *path, int expected_result, const char *expected_raw_oid)
|
||||
static void assert_tree_from_path(
|
||||
git_tree *root,
|
||||
const char *path,
|
||||
const char *expected_entry_name)
|
||||
{
|
||||
git_tree *containing_tree = NULL;
|
||||
git_tree_entry *entry;
|
||||
|
||||
cl_assert(git_tree_get_subtree(&containing_tree, root, path) == expected_result);
|
||||
|
||||
if (containing_tree == NULL && expected_result != 0)
|
||||
return;
|
||||
|
||||
cl_assert(containing_tree != NULL && expected_result == 0);
|
||||
|
||||
cl_git_pass(git_oid_streq(git_object_id((const git_object *)containing_tree), expected_raw_oid));
|
||||
|
||||
git_tree_free(containing_tree);
|
||||
}
|
||||
|
||||
static void assert_tree_from_path_klass(git_tree *root, const char *path, int expected_result, const char *expected_raw_oid)
|
||||
{
|
||||
assert_tree_from_path(root, path, GIT_ERROR, expected_raw_oid);
|
||||
cl_assert(giterr_last()->klass == expected_result);
|
||||
cl_git_pass(git_tree_entry_bypath(&entry, root, path));
|
||||
cl_assert_equal_s(git_tree_entry_name(entry), expected_entry_name);
|
||||
git_tree_entry_free(entry);
|
||||
}
|
||||
|
||||
void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void)
|
||||
{
|
||||
/* Will return self if given a one path segment... */
|
||||
assert_tree_from_path(tree, "README", 0, tree_with_subtrees_oid);
|
||||
|
||||
/* ...even one that lead to a non existent tree entry. */
|
||||
assert_tree_from_path(tree, "i-do-not-exist.txt", 0, tree_with_subtrees_oid);
|
||||
|
||||
/* Will return fgh tree oid given this following path... */
|
||||
assert_tree_from_path(tree, "ab/de/fgh/1.txt", 0, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54");
|
||||
|
||||
/* ... and ab tree oid given this one. */
|
||||
assert_tree_from_path(tree, "ab/de", 0, "f1425cef211cc08caa31e7b545ffb232acb098c3");
|
||||
git_tree_entry *e;
|
||||
|
||||
/* Will succeed if given a valid path which leads to a tree entry which doesn't exist */
|
||||
assert_tree_from_path(tree, "ab/de/fgh/i-do-not-exist.txt", 0, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54");
|
||||
}
|
||||
assert_tree_from_path(tree, "README", "README");
|
||||
assert_tree_from_path(tree, "ab/de/fgh/1.txt", "1.txt");
|
||||
assert_tree_from_path(tree, "ab/de/fgh", "fgh");
|
||||
assert_tree_from_path(tree, "ab/de/fgh/", "fgh");
|
||||
assert_tree_from_path(tree, "ab/de", "de");
|
||||
assert_tree_from_path(tree, "ab/", "ab");
|
||||
assert_tree_from_path(tree, "ab/de/", "de");
|
||||
|
||||
void test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment(void)
|
||||
{
|
||||
assert_tree_from_path(tree, "nope/de/fgh/1.txt", GIT_ENOTFOUND, NULL);
|
||||
assert_tree_from_path(tree, "ab/me-neither/fgh/2.txt", GIT_ENOTFOUND, NULL);
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "i-do-not-exist.txt"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "README/"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/de/fgh/i-do-not-exist.txt"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "nope/de/fgh/1.txt"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt/"));
|
||||
}
|
||||
|
||||
void test_object_tree_frompath__fail_when_processing_an_invalid_path(void)
|
||||
{
|
||||
assert_tree_from_path_klass(tree, "/", GITERR_INVALID, NULL);
|
||||
assert_tree_from_path_klass(tree, "/ab", GITERR_INVALID, NULL);
|
||||
assert_tree_from_path_klass(tree, "/ab/de", GITERR_INVALID, NULL);
|
||||
assert_tree_from_path_klass(tree, "ab/", GITERR_INVALID, NULL);
|
||||
assert_tree_from_path_klass(tree, "ab//de", GITERR_INVALID, NULL);
|
||||
assert_tree_from_path_klass(tree, "ab/de/", GITERR_INVALID, NULL);
|
||||
git_tree_entry *e;
|
||||
|
||||
cl_must_fail(git_tree_entry_bypath(&e, tree, "/"));
|
||||
cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab"));
|
||||
cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab/de"));
|
||||
cl_must_fail(git_tree_entry_bypath(&e, tree, "ab//de"));
|
||||
}
|
||||
|
36
tests-clar/odb/foreach.c
Normal file
36
tests-clar/odb/foreach.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "odb.h"
|
||||
#include "git2/odb_backend.h"
|
||||
#include "pack.h"
|
||||
|
||||
static git_odb *_odb;
|
||||
static git_repository *_repo;
|
||||
static int nobj;
|
||||
|
||||
void test_odb_foreach__initialize(void)
|
||||
{
|
||||
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
|
||||
git_repository_odb(&_odb, _repo);
|
||||
}
|
||||
|
||||
void test_odb_foreach__cleanup(void)
|
||||
{
|
||||
git_odb_free(_odb);
|
||||
git_repository_free(_repo);
|
||||
}
|
||||
|
||||
static int foreach_cb(git_oid *oid, void *data)
|
||||
{
|
||||
GIT_UNUSED(data);
|
||||
GIT_UNUSED(oid);
|
||||
|
||||
nobj++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_odb_foreach__foreach(void)
|
||||
{
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
|
||||
cl_assert(nobj == 1683);
|
||||
}
|
128
tests-clar/refs/branches/foreach.c
Normal file
128
tests-clar/refs/branches/foreach.c
Normal file
@ -0,0 +1,128 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "refs.h"
|
||||
#include "branch.h"
|
||||
|
||||
static git_repository *repo;
|
||||
static git_reference *fake_remote;
|
||||
|
||||
void test_refs_branches_foreach__initialize(void)
|
||||
{
|
||||
git_oid id;
|
||||
|
||||
cl_fixture_sandbox("testrepo.git");
|
||||
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
|
||||
cl_git_pass(git_reference_create_oid(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
|
||||
}
|
||||
|
||||
void test_refs_branches_foreach__cleanup(void)
|
||||
{
|
||||
git_reference_free(fake_remote);
|
||||
git_repository_free(repo);
|
||||
|
||||
cl_fixture_cleanup("testrepo.git");
|
||||
}
|
||||
|
||||
static int count_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload)
|
||||
{
|
||||
int *count;
|
||||
|
||||
GIT_UNUSED(branch_type);
|
||||
GIT_UNUSED(branch_name);
|
||||
|
||||
count = (int *)payload;
|
||||
(*count)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void assert_retrieval(unsigned int flags, unsigned int expected_count)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
cl_git_pass(git_branch_foreach(repo, flags, count_branch_list_cb, &count));
|
||||
|
||||
cl_assert_equal_i(expected_count, count);
|
||||
}
|
||||
|
||||
void test_refs_branches_foreach__retrieve_all_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 10);
|
||||
}
|
||||
|
||||
void test_refs_branches_foreach__retrieve_remote_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_REMOTE, 2);
|
||||
}
|
||||
|
||||
void test_refs_branches_foreach__retrieve_local_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_LOCAL, 8);
|
||||
}
|
||||
|
||||
struct expectations {
|
||||
const char *branch_name;
|
||||
int encounters;
|
||||
};
|
||||
|
||||
static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
while (findings[pos].branch_name)
|
||||
{
|
||||
if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) {
|
||||
cl_assert_equal_i(1, findings[pos].encounters);
|
||||
return;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
cl_fail("expected branch not found in list.");
|
||||
}
|
||||
|
||||
static int contains_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload)
|
||||
{
|
||||
int pos = 0;
|
||||
struct expectations *exp;
|
||||
|
||||
GIT_UNUSED(branch_type);
|
||||
|
||||
exp = (struct expectations *)payload;
|
||||
|
||||
while (exp[pos].branch_name)
|
||||
{
|
||||
if (strcmp(branch_name, exp[pos].branch_name) == 0)
|
||||
exp[pos].encounters++;
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $ git branch -r
|
||||
* nulltoken/HEAD -> nulltoken/master
|
||||
* nulltoken/master
|
||||
*/
|
||||
void test_refs_branches_foreach__retrieve_remote_symbolic_HEAD_when_present(void)
|
||||
{
|
||||
struct expectations exp[] = {
|
||||
{ "nulltoken/HEAD", 0 },
|
||||
{ "nulltoken/master", 0 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
git_reference_free(fake_remote);
|
||||
cl_git_pass(git_reference_create_symbolic(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0));
|
||||
|
||||
assert_retrieval(GIT_BRANCH_REMOTE, 3);
|
||||
|
||||
cl_git_pass(git_branch_foreach(repo, GIT_BRANCH_REMOTE, contains_branch_list_cb, &exp));
|
||||
|
||||
assert_branch_has_been_found(exp, "nulltoken/HEAD");
|
||||
assert_branch_has_been_found(exp, "nulltoken/HEAD");
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "refs.h"
|
||||
#include "branch.h"
|
||||
|
||||
static git_repository *repo;
|
||||
static git_strarray branch_list;
|
||||
static git_reference *fake_remote;
|
||||
|
||||
void test_refs_branches_listall__initialize(void)
|
||||
{
|
||||
git_oid id;
|
||||
|
||||
cl_fixture_sandbox("testrepo.git");
|
||||
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
|
||||
cl_git_pass(git_reference_create_oid(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
|
||||
}
|
||||
|
||||
void test_refs_branches_listall__cleanup(void)
|
||||
{
|
||||
git_strarray_free(&branch_list);
|
||||
git_reference_free(fake_remote);
|
||||
git_repository_free(repo);
|
||||
|
||||
cl_fixture_cleanup("testrepo.git");
|
||||
}
|
||||
|
||||
static void assert_retrieval(unsigned int flags, unsigned int expected_count)
|
||||
{
|
||||
cl_git_pass(git_branch_list(&branch_list, repo, flags));
|
||||
|
||||
cl_assert_equal_i(branch_list.count, expected_count);
|
||||
}
|
||||
|
||||
void test_refs_branches_listall__retrieve_all_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 9);
|
||||
}
|
||||
|
||||
void test_refs_branches_listall__retrieve_remote_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_REMOTE, 2);
|
||||
}
|
||||
|
||||
void test_refs_branches_listall__retrieve_local_branches(void)
|
||||
{
|
||||
assert_retrieval(GIT_BRANCH_LOCAL, 7);
|
||||
}
|
||||
|
||||
static void assert_branch_list_contains(git_strarray *branches, const char* expected_branch_name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < branches->count; i++) {
|
||||
if (strcmp(expected_branch_name, branches->strings[i]) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
cl_fail("expected branch not found in list.");
|
||||
}
|
||||
|
||||
/*
|
||||
* $ git branch -r
|
||||
* nulltoken/HEAD -> nulltoken/master
|
||||
* nulltoken/master
|
||||
*/
|
||||
void test_refs_branches_listall__retrieve_remote_symbolic_HEAD_when_present(void)
|
||||
{
|
||||
git_reference_free(fake_remote);
|
||||
cl_git_pass(git_reference_create_symbolic(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0));
|
||||
|
||||
cl_git_pass(git_branch_list(&branch_list, repo, GIT_BRANCH_REMOTE));
|
||||
|
||||
cl_assert_equal_i(3, branch_list.count);
|
||||
assert_branch_list_contains(&branch_list, "remotes/nulltoken/HEAD");
|
||||
assert_branch_list_contains(&branch_list, "remotes/nulltoken/master");
|
||||
}
|
70
tests-clar/refs/foreachglob.c
Normal file
70
tests-clar/refs/foreachglob.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "refs.h"
|
||||
|
||||
static git_repository *repo;
|
||||
static git_reference *fake_remote;
|
||||
|
||||
void test_refs_foreachglob__initialize(void)
|
||||
{
|
||||
git_oid id;
|
||||
|
||||
cl_fixture_sandbox("testrepo.git");
|
||||
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
|
||||
cl_git_pass(git_reference_create_oid(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__cleanup(void)
|
||||
{
|
||||
git_reference_free(fake_remote);
|
||||
git_repository_free(repo);
|
||||
|
||||
cl_fixture_cleanup("testrepo.git");
|
||||
}
|
||||
|
||||
static int count_cb(const char *reference_name, void *payload)
|
||||
{
|
||||
int *count = (int *)payload;
|
||||
|
||||
GIT_UNUSED(reference_name);
|
||||
|
||||
(*count)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void assert_retrieval(const char *glob, unsigned int flags, int expected_count)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
cl_git_pass(git_reference_foreach_glob(repo, glob, flags, count_cb, &count));
|
||||
|
||||
cl_assert_equal_i(expected_count, count);
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__retrieve_all_refs(void)
|
||||
{
|
||||
/* 7 heads (including one packed head) + 1 note + 2 remotes + 6 tags */
|
||||
assert_retrieval("*", GIT_REF_LISTALL, 17);
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__retrieve_remote_branches(void)
|
||||
{
|
||||
assert_retrieval("refs/remotes/*", GIT_REF_LISTALL, 2);
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__retrieve_local_branches(void)
|
||||
{
|
||||
assert_retrieval("refs/heads/*", GIT_REF_LISTALL, 8);
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__retrieve_partially_named_references(void)
|
||||
{
|
||||
/*
|
||||
* refs/heads/packed-test, refs/heads/test
|
||||
* refs/remotes/test/master, refs/tags/test
|
||||
*/
|
||||
|
||||
assert_retrieval("*test*", GIT_REF_LISTALL, 4);
|
||||
}
|
@ -16,12 +16,12 @@ static git_repository *g_repo;
|
||||
|
||||
void test_refs_read__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo");
|
||||
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
|
||||
}
|
||||
|
||||
void test_refs_read__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
git_repository_free(g_repo);
|
||||
}
|
||||
|
||||
void test_refs_read__loose_tag(void)
|
||||
@ -192,3 +192,13 @@ void test_refs_read__loose_first(void)
|
||||
|
||||
git_reference_free(reference);
|
||||
}
|
||||
|
||||
void test_refs_read__unfound_return_ENOTFOUND(void)
|
||||
{
|
||||
git_reference *reference;
|
||||
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "test/master"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/test/master"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ static void assert_signature(git_signature *expected, git_signature *actual)
|
||||
// Fixture setup and teardown
|
||||
void test_refs_reflog__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo");
|
||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||
}
|
||||
|
||||
void test_refs_reflog__cleanup(void)
|
||||
@ -61,7 +61,7 @@ void test_refs_reflog__write_then_read(void)
|
||||
cl_git_pass(git_reflog_write(ref, &oid, committer, commit_msg));
|
||||
|
||||
/* Reopen a new instance of the repository */
|
||||
cl_git_pass(git_repository_open(&repo2, "testrepo"));
|
||||
cl_git_pass(git_repository_open(&repo2, "testrepo.git"));
|
||||
|
||||
/* Lookup the preivously created branch */
|
||||
cl_git_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref));
|
||||
@ -121,3 +121,44 @@ void test_refs_reflog__dont_write_bad(void)
|
||||
|
||||
git_reference_free(ref);
|
||||
}
|
||||
|
||||
void test_refs_reflog__renaming_the_reference_moves_the_reflog(void)
|
||||
{
|
||||
git_reference *master;
|
||||
git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT;
|
||||
|
||||
git_buf_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR);
|
||||
git_buf_puts(&moved_log_path, git_buf_cstr(&master_log_path));
|
||||
git_buf_joinpath(&master_log_path, git_buf_cstr(&master_log_path), "refs/heads/master");
|
||||
git_buf_joinpath(&moved_log_path, git_buf_cstr(&moved_log_path), "refs/moved");
|
||||
|
||||
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&master_log_path)));
|
||||
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path)));
|
||||
|
||||
cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
|
||||
cl_git_pass(git_reference_rename(master, "refs/moved", 0));
|
||||
|
||||
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path)));
|
||||
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&moved_log_path)));
|
||||
|
||||
git_reference_free(master);
|
||||
git_buf_free(&moved_log_path);
|
||||
git_buf_free(&master_log_path);
|
||||
}
|
||||
static void assert_has_reflog(bool expected_result, const char *name)
|
||||
{
|
||||
git_reference *ref;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&ref, g_repo, name));
|
||||
|
||||
cl_assert_equal_i(expected_result, git_reference_has_log(ref));
|
||||
|
||||
git_reference_free(ref);
|
||||
}
|
||||
|
||||
void test_refs_reflog__reference_has_reflog(void)
|
||||
{
|
||||
assert_has_reflog(true, "HEAD");
|
||||
assert_has_reflog(true, "refs/heads/master");
|
||||
assert_has_reflog(false, "refs/heads/subtrees");
|
||||
}
|
||||
|
49
tests-clar/refs/remotetracking.c
Normal file
49
tests-clar/refs/remotetracking.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
static git_repository *g_repo;
|
||||
|
||||
void test_refs_remotetracking__initialize(void)
|
||||
{
|
||||
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
|
||||
}
|
||||
|
||||
void test_refs_remotetracking__cleanup(void)
|
||||
{
|
||||
git_repository_free(g_repo);
|
||||
}
|
||||
|
||||
void test_refs_remotetracking__unfound_returns_GIT_ENOTFOUND(void)
|
||||
{
|
||||
git_reference *branch, *tracking;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/heads/subtrees"));
|
||||
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_remote_tracking_from_branch(&tracking, branch));
|
||||
|
||||
git_reference_free(branch);
|
||||
}
|
||||
|
||||
void test_refs_remotetracking__retrieving_from_a_non_head_fails(void)
|
||||
{
|
||||
git_reference *branch, *tracking;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/tags/e90810b"));
|
||||
|
||||
cl_git_fail(git_reference_remote_tracking_from_branch(&tracking, branch));
|
||||
|
||||
git_reference_free(branch);
|
||||
}
|
||||
|
||||
void test_refs_remotetracking__can_retrieve_a_remote_tracking_branch_reference(void)
|
||||
{
|
||||
git_reference *branch, *tracking;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/heads/master"));
|
||||
|
||||
cl_git_pass(git_reference_remote_tracking_from_branch(&tracking, branch));
|
||||
|
||||
cl_assert_equal_s("refs/remotes/test/master", git_reference_name(tracking));
|
||||
|
||||
git_reference_free(branch);
|
||||
git_reference_free(tracking);
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
#include "git2/revparse.h"
|
||||
#include "buffer.h"
|
||||
#include "refs.h"
|
||||
#include "path.h"
|
||||
|
||||
static git_repository *g_repo;
|
||||
static git_object *g_obj;
|
||||
@ -9,170 +12,394 @@ static char g_orig_tz[16] = {0};
|
||||
|
||||
|
||||
/* Helpers */
|
||||
static void test_object(const char *spec, const char *expected_oid)
|
||||
static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo)
|
||||
{
|
||||
char objstr[64] = {0};
|
||||
char objstr[64] = {0};
|
||||
git_object *obj = NULL;
|
||||
int error;
|
||||
|
||||
cl_git_pass(git_revparse_single(&g_obj, g_repo, spec));
|
||||
git_oid_fmt(objstr, git_object_id(g_obj));
|
||||
cl_assert_equal_s(objstr, expected_oid);
|
||||
error = git_revparse_single(&obj, repo, spec);
|
||||
|
||||
git_object_free(g_obj);
|
||||
g_obj = NULL;
|
||||
if (expected_oid != NULL) {
|
||||
cl_assert_equal_i(0, error);
|
||||
git_oid_fmt(objstr, git_object_id(obj));
|
||||
cl_assert_equal_s(objstr, expected_oid);
|
||||
} else
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, error);
|
||||
|
||||
git_object_free(obj);
|
||||
}
|
||||
|
||||
static void test_object(const char *spec, const char *expected_oid)
|
||||
{
|
||||
test_object_inrepo(spec, expected_oid, g_repo);
|
||||
}
|
||||
|
||||
void test_refs_revparse__initialize(void)
|
||||
{
|
||||
char *tz = cl_getenv("TZ");
|
||||
if (tz)
|
||||
strcpy(g_orig_tz, tz);
|
||||
cl_setenv("TZ", "UTC");
|
||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||
char *tz = cl_getenv("TZ");
|
||||
if (tz)
|
||||
strcpy(g_orig_tz, tz);
|
||||
cl_setenv("TZ", "UTC");
|
||||
|
||||
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
|
||||
}
|
||||
|
||||
void test_refs_revparse__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
g_obj = NULL;
|
||||
cl_setenv("TZ", g_orig_tz);
|
||||
git_repository_free(g_repo);
|
||||
g_obj = NULL;
|
||||
cl_setenv("TZ", g_orig_tz);
|
||||
}
|
||||
|
||||
|
||||
void test_refs_revparse__nonexistant_object(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist^1"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist~2"));
|
||||
test_object("this-does-not-exist", NULL);
|
||||
test_object("this-does-not-exist^1", NULL);
|
||||
test_object("this-does-not-exist~2", NULL);
|
||||
}
|
||||
|
||||
void test_refs_revparse__invalid_reference_name(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense^1"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense~2"));
|
||||
}
|
||||
|
||||
void test_refs_revparse__shas(void)
|
||||
{
|
||||
test_object("c47800c7266a2be04c571c04d5a6614691ea99bd", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("c47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("c47800c7266a2be04c571c04d5a6614691ea99bd", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("c47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
}
|
||||
|
||||
void test_refs_revparse__head(void)
|
||||
{
|
||||
test_object("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
}
|
||||
|
||||
void test_refs_revparse__full_refs(void)
|
||||
{
|
||||
test_object("refs/heads/master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("refs/heads/test", "e90810b8df3e80c413d903f631643c716887138d");
|
||||
test_object("refs/tags/test", "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
|
||||
test_object("refs/heads/master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("refs/heads/test", "e90810b8df3e80c413d903f631643c716887138d");
|
||||
test_object("refs/tags/test", "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
|
||||
}
|
||||
|
||||
void test_refs_revparse__partial_refs(void)
|
||||
{
|
||||
test_object("point_to_blob", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
test_object("packed-test", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
|
||||
test_object("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object("point_to_blob", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
test_object("packed-test", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
|
||||
test_object("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
}
|
||||
|
||||
void test_refs_revparse__describe_output(void)
|
||||
{
|
||||
test_object("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("not-good", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("not-good", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
}
|
||||
|
||||
void test_refs_revparse__nth_parent(void)
|
||||
{
|
||||
test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("be3563a^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("be3563a^1^1", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
|
||||
test_object("be3563a^2^1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("be3563a^0", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("be3563a^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("be3563a^1^1", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
|
||||
test_object("be3563a^2^1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("be3563a^0", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
|
||||
test_object("be3563a^42", NULL);
|
||||
}
|
||||
|
||||
void test_refs_revparse__not_tag(void)
|
||||
{
|
||||
test_object("point_to_blob^{}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
test_object("wrapped_tag^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("point_to_blob^{}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
test_object("wrapped_tag^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
}
|
||||
|
||||
void test_refs_revparse__to_type(void)
|
||||
{
|
||||
test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
|
||||
test_object("point_to_blob^{blob}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
|
||||
test_object("point_to_blob^{blob}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}"));
|
||||
}
|
||||
|
||||
void test_refs_revparse__linear_history(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "foo~bar"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master~bar"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "foo~bar"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master~bar"));
|
||||
|
||||
test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master~2", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master~1~1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master~2", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master~1~1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
}
|
||||
|
||||
void test_refs_revparse__chaining(void)
|
||||
{
|
||||
test_object("master~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master~1^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("master^1^2~1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("master^1^1^1^1^1", "8496071c1b46c854b31185ea97743be6a8774479");
|
||||
test_object("master~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master~1^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object("master^1^2~1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("master^1^1^1^1^1", "8496071c1b46c854b31185ea97743be6a8774479");
|
||||
}
|
||||
|
||||
void test_refs_revparse__reflog(void)
|
||||
void test_refs_revparse__upstream(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-xyz}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-0}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{1000}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "e90810b@{u}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "refs/tags/e90810b@{u}"));
|
||||
|
||||
test_object("@{-2}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("@{-1}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object("master@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("refs/heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
}
|
||||
|
||||
void test_refs_revparse__ordinal(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{-2}"));
|
||||
|
||||
test_object("nope@{0}", NULL);
|
||||
test_object("master@{31415}", NULL);
|
||||
test_object("@{1000}", NULL);
|
||||
test_object("@{2}", NULL);
|
||||
|
||||
test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
|
||||
test_object("master@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("refs/heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
}
|
||||
|
||||
void test_refs_revparse__previous_head(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-xyz}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-0}"));
|
||||
|
||||
test_object("@{-42}", NULL);
|
||||
|
||||
test_object("@{-2}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("@{-1}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
}
|
||||
|
||||
static void create_fake_stash_reference_and_reflog(git_repository *repo)
|
||||
{
|
||||
git_reference *master;
|
||||
git_buf log_path = GIT_BUF_INIT;
|
||||
|
||||
git_buf_joinpath(&log_path, git_repository_path(repo), "logs/refs/fakestash");
|
||||
|
||||
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path)));
|
||||
|
||||
cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master"));
|
||||
cl_git_pass(git_reference_rename(master, "refs/fakestash", 0));
|
||||
|
||||
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
|
||||
|
||||
git_buf_free(&log_path);
|
||||
git_reference_free(master);
|
||||
}
|
||||
|
||||
void test_refs_revparse__reflog_of_a_ref_under_refs(void)
|
||||
{
|
||||
git_repository *repo = cl_git_sandbox_init("testrepo.git");
|
||||
|
||||
test_object_inrepo("refs/fakestash", NULL, repo);
|
||||
|
||||
create_fake_stash_reference_and_reflog(repo);
|
||||
|
||||
/*
|
||||
* $ git reflog -1 refs/fakestash
|
||||
* a65fedf refs/fakestash@{0}: commit: checking in
|
||||
*
|
||||
* $ git reflog -1 refs/fakestash@{0}
|
||||
* a65fedf refs/fakestash@{0}: commit: checking in
|
||||
*
|
||||
* $ git reflog -1 fakestash
|
||||
* a65fedf fakestash@{0}: commit: checking in
|
||||
*
|
||||
* $ git reflog -1 fakestash@{0}
|
||||
* a65fedf fakestash@{0}: commit: checking in
|
||||
*/
|
||||
test_object_inrepo("refs/fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
|
||||
test_object_inrepo("refs/fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
|
||||
test_object_inrepo("fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
|
||||
test_object_inrepo("fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
|
||||
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
void test_refs_revparse__revwalk(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/not found in any commit}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/merge}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/((}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/not found in any commit}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/merge}"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/((}"));
|
||||
|
||||
test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a");
|
||||
}
|
||||
|
||||
void test_refs_revparse__date(void)
|
||||
{
|
||||
test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master@{2012-4-30 10:23:20 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{2012-4-30 18:24 -0800}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master@{2012-4-30 23:24 -0300}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
/*
|
||||
* $ git reflog HEAD --date=iso
|
||||
* a65fedf HEAD@{2012-04-30 08:23:41 -0900}: checkout: moving from br2 to master
|
||||
* a4a7dce HEAD@{2012-04-30 08:23:37 -0900}: commit: checking in
|
||||
* c47800c HEAD@{2012-04-30 08:23:28 -0900}: checkout: moving from master to br2
|
||||
* a65fedf HEAD@{2012-04-30 08:23:23 -0900}: commit:
|
||||
* be3563a HEAD@{2012-04-30 10:22:43 -0700}: clone: from /Users/ben/src/libgit2/tes
|
||||
*
|
||||
* $ git reflog HEAD --date=raw
|
||||
* a65fedf HEAD@{1335806621 -0900}: checkout: moving from br2 to master
|
||||
* a4a7dce HEAD@{1335806617 -0900}: commit: checking in
|
||||
* c47800c HEAD@{1335806608 -0900}: checkout: moving from master to br2
|
||||
* a65fedf HEAD@{1335806603 -0900}: commit:
|
||||
* be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour
|
||||
*/
|
||||
test_object("HEAD@{10 years ago}", NULL);
|
||||
|
||||
/* Core git gives a65fedf, because they don't take time zones into account. */
|
||||
test_object("master@{1335806640}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("HEAD@{2 days ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
|
||||
/*
|
||||
* $ git reflog master --date=iso
|
||||
* a65fedf master@{2012-04-30 09:23:23 -0800}: commit: checking in
|
||||
* be3563a master@{2012-04-30 09:22:43 -0800}: clone: from /Users/ben/src...
|
||||
*
|
||||
* $ git reflog master --date=raw
|
||||
* a65fedf master@{1335806603 -0800}: commit: checking in
|
||||
* be3563a master@{1335806563 -0800}: clone: from /Users/ben/src/libgit2/tests/reso
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}"
|
||||
* warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800.
|
||||
*/
|
||||
test_object("master@{2012-04-30 17:22:42 +0000}", NULL);
|
||||
test_object("master@{2012-04-30 09:22:42 -0800}", NULL);
|
||||
|
||||
/*
|
||||
* $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}"
|
||||
* be3563a master@{Mon Apr 30 09:22:43 2012 -0800}: clone: from /Users/ben/src/libg
|
||||
*/
|
||||
test_object("master@{2012-04-30 17:22:43 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
test_object("master@{2012-04-30 09:22:43 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
|
||||
/*
|
||||
* $ git reflog -1 "master@{2012-4-30 09:23:27 -0800}"
|
||||
* a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in
|
||||
*/
|
||||
test_object("master@{2012-4-30 09:23:27 -0800}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
|
||||
/*
|
||||
* $ git reflog -1 master@{2012-05-03}
|
||||
* a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in
|
||||
*/
|
||||
test_object("master@{2012-05-03}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
|
||||
/*
|
||||
* $ git reflog -1 "master@{1335806603}"
|
||||
* a65fedf
|
||||
*
|
||||
* $ git reflog -1 "master@{1335806602}"
|
||||
* be3563a
|
||||
*/
|
||||
test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
|
||||
test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
}
|
||||
|
||||
void test_refs_revparse__colon(void)
|
||||
{
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":/"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":/not found in any commit"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, "master:"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":/"));
|
||||
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README"));
|
||||
|
||||
test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f");
|
||||
test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b");
|
||||
test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
|
||||
test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
|
||||
test_object(":/Merge", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object(":/one", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object(":/packed commit t", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9");
|
||||
test_object(":/not found in any commit", NULL);
|
||||
test_object("subtrees:ab/42.txt", NULL);
|
||||
test_object("subtrees:ab/4.txt/nope", NULL);
|
||||
test_object("subtrees:nope", NULL);
|
||||
test_object("test/master^1:branch_file.txt", NULL);
|
||||
|
||||
/* From tags */
|
||||
test_object("test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
|
||||
test_object("tags/test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
|
||||
test_object("e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
|
||||
test_object("tags/e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf");
|
||||
|
||||
/* From commits */
|
||||
test_object("a65f:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
|
||||
|
||||
/* From trees */
|
||||
test_object("a65f^{tree}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
|
||||
test_object("944c:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc");
|
||||
|
||||
/* Retrieving trees */
|
||||
test_object("master:", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
|
||||
test_object("subtrees:", "ae90f12eea699729ed24555e40b9fd669da12a12");
|
||||
test_object("subtrees:ab", "f1425cef211cc08caa31e7b545ffb232acb098c3");
|
||||
test_object("subtrees:ab/", "f1425cef211cc08caa31e7b545ffb232acb098c3");
|
||||
|
||||
/* Retrieving blobs */
|
||||
test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f");
|
||||
test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b");
|
||||
test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
|
||||
test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
|
||||
test_object(":/Merge", "a4a7dce85cf63874e984719f4fdd239f5145052f");
|
||||
test_object(":/one", "c47800c7266a2be04c571c04d5a6614691ea99bd");
|
||||
test_object(":/packed commit t", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9");
|
||||
test_object("test/master^2:branch_file.txt", "45b983be36b73c0788dc9cbcb76cbb80fc7bb057");
|
||||
}
|
||||
|
||||
void test_refs_revparse__disambiguation(void)
|
||||
{
|
||||
/*
|
||||
* $ git show e90810b
|
||||
* tag e90810b
|
||||
* Tagger: Vicent Marti <tanoku@gmail.com>
|
||||
* Date: Thu Aug 12 03:59:17 2010 +0200
|
||||
*
|
||||
* This is a very simple tag.
|
||||
*
|
||||
* commit e90810b8df3e80c413d903f631643c716887138d
|
||||
* Author: Vicent Marti <tanoku@gmail.com>
|
||||
* Date: Thu Aug 5 18:42:20 2010 +0200
|
||||
*
|
||||
* Test commit 2
|
||||
*
|
||||
* diff --git a/readme.txt b/readme.txt
|
||||
* index 6336846..0266163 100644
|
||||
* --- a/readme.txt
|
||||
* +++ b/readme.txt
|
||||
* @@ -1 +1,2 @@
|
||||
* Testing a readme.txt
|
||||
* +Now we add a single line here
|
||||
*
|
||||
* $ git show-ref e90810b
|
||||
* 7b4384978d2493e851f9cca7858815fac9b10980 refs/tags/e90810b
|
||||
*
|
||||
*/
|
||||
test_object("e90810b", "7b4384978d2493e851f9cca7858815fac9b10980");
|
||||
|
||||
/*
|
||||
* $ git show e90810
|
||||
* commit e90810b8df3e80c413d903f631643c716887138d
|
||||
* Author: Vicent Marti <tanoku@gmail.com>
|
||||
* Date: Thu Aug 5 18:42:20 2010 +0200
|
||||
*
|
||||
* Test commit 2
|
||||
*
|
||||
* diff --git a/readme.txt b/readme.txt
|
||||
* index 6336846..0266163 100644
|
||||
* --- a/readme.txt
|
||||
* +++ b/readme.txt
|
||||
* @@ -1 +1,2 @@
|
||||
* Testing a readme.txt
|
||||
* +Now we add a single line here
|
||||
*/
|
||||
test_object("e90810", "e90810b8df3e80c413d903f631643c716887138d");
|
||||
}
|
||||
|
@ -170,10 +170,21 @@ static void assert_config_entry_on_init_bytype(const char *config_key, int expec
|
||||
{
|
||||
git_config *config;
|
||||
int current_value;
|
||||
git_buf repo_path = GIT_BUF_INIT;
|
||||
|
||||
cl_set_cleanup(&cleanup_repository, "config_entry");
|
||||
|
||||
cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", is_bare));
|
||||
|
||||
cl_git_pass(git_buf_puts(&repo_path, "config_entry/test."));
|
||||
|
||||
if (!is_bare)
|
||||
cl_git_pass(git_buf_puts(&repo_path, "non."));
|
||||
|
||||
cl_git_pass(git_buf_puts(&repo_path, "bare.git"));
|
||||
|
||||
cl_git_pass(git_repository_init(&_repo, git_buf_cstr(&repo_path), is_bare));
|
||||
|
||||
git_buf_free(&repo_path);
|
||||
|
||||
git_repository_config(&config, _repo);
|
||||
|
||||
if (expected_value >= 0) {
|
||||
@ -223,16 +234,18 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
|
||||
int current_value;
|
||||
|
||||
/* Init a new repo */
|
||||
test_repo_init__detect_ignorecase();
|
||||
cl_set_cleanup(&cleanup_repository, "not.overwrite.git");
|
||||
cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
|
||||
|
||||
/* Change the "core.ignorecase" config value to something unlikely */
|
||||
git_repository_config(&config, _repo);
|
||||
git_config_set_int32(config, "core.ignorecase", 42);
|
||||
git_config_free(config);
|
||||
git_repository_free(_repo);
|
||||
_repo = NULL;
|
||||
|
||||
/* Reinit the repository */
|
||||
cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", 1));
|
||||
cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
|
||||
git_repository_config(&config, _repo);
|
||||
|
||||
/* Ensure the "core.ignorecase" config value hasn't been updated */
|
||||
@ -242,6 +255,40 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
|
||||
git_config_free(config);
|
||||
}
|
||||
|
||||
void test_repo_init__reinit_overwrites_filemode(void)
|
||||
{
|
||||
git_config *config;
|
||||
int expected, current_value;
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
expected = false;
|
||||
#else
|
||||
expected = true;
|
||||
#endif
|
||||
|
||||
/* Init a new repo */
|
||||
cl_set_cleanup(&cleanup_repository, "overwrite.git");
|
||||
cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
|
||||
|
||||
|
||||
/* Change the "core.filemode" config value to something unlikely */
|
||||
git_repository_config(&config, _repo);
|
||||
git_config_set_bool(config, "core.filemode", !expected);
|
||||
git_config_free(config);
|
||||
git_repository_free(_repo);
|
||||
_repo = NULL;
|
||||
|
||||
/* Reinit the repository */
|
||||
cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
|
||||
git_repository_config(&config, _repo);
|
||||
|
||||
/* Ensure the "core.filemode" config value has been reset */
|
||||
cl_git_pass(git_config_get_bool(¤t_value, config, "core.filemode"));
|
||||
cl_assert_equal_i(expected, current_value);
|
||||
|
||||
git_config_free(config);
|
||||
}
|
||||
|
||||
void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
|
||||
{
|
||||
assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true);
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "buffer.h"
|
||||
#include "posix.h"
|
||||
#include "util.h"
|
||||
#include "path.h"
|
||||
#include "fileops.h"
|
||||
|
||||
static git_repository *repo;
|
||||
|
||||
@ -16,7 +18,7 @@ void test_repo_setters__cleanup(void)
|
||||
{
|
||||
git_repository_free(repo);
|
||||
cl_fixture_cleanup("testrepo.git");
|
||||
cl_must_pass(p_rmdir("new_workdir"));
|
||||
cl_fixture_cleanup("new_workdir");
|
||||
}
|
||||
|
||||
void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one(void)
|
||||
@ -24,7 +26,7 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
|
||||
cl_assert(git_repository_is_bare(repo) == 1);
|
||||
|
||||
cl_assert(git_repository_workdir(repo) == NULL);
|
||||
cl_git_pass(git_repository_set_workdir(repo, "./new_workdir"));
|
||||
cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false));
|
||||
|
||||
cl_assert(git_repository_workdir(repo) != NULL);
|
||||
cl_assert(git_repository_is_bare(repo) == 0);
|
||||
@ -32,9 +34,30 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
|
||||
|
||||
void test_repo_setters__setting_a_workdir_prettifies_its_path(void)
|
||||
{
|
||||
cl_git_pass(git_repository_set_workdir(repo, "./new_workdir"));
|
||||
cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false));
|
||||
|
||||
cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0);
|
||||
cl_assert(git__suffixcmp(git_repository_workdir(repo), "new_workdir/") == 0);
|
||||
}
|
||||
|
||||
void test_repo_setters__setting_a_workdir_creates_a_gitlink(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
const char *val;
|
||||
git_buf content = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", true));
|
||||
|
||||
cl_assert(git_path_isfile("./new_workdir/.git"));
|
||||
|
||||
cl_git_pass(git_futils_readbuffer(&content, "./new_workdir/.git"));
|
||||
cl_assert(git__prefixcmp(git_buf_cstr(&content), "gitdir: ") == 0);
|
||||
cl_assert(git__suffixcmp(git_buf_cstr(&content), "testrepo.git/") == 0);
|
||||
git_buf_free(&content);
|
||||
|
||||
cl_git_pass(git_repository_config(&cfg, repo));
|
||||
cl_git_pass(git_config_get_string(&val, cfg, "core.worktree"));
|
||||
cl_assert(git__suffixcmp(val, "new_workdir/") == 0);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_one_properly_honors_the_refcount(void)
|
||||
|
Binary file not shown.
@ -6,3 +6,4 @@ a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6
|
||||
f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer <arrbee@arrbee.com> 1328653313 -0800 commit: Some whitespace only changes for testing purposes
|
||||
a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer <arrbee@arrbee.com> 1332734901 -0700 commit: added files in sub/sub
|
||||
217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer <arrbee@arrbee.com> 1332735555 -0700 commit: adding more files in sub for tree status
|
||||
24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah <yoram.harmelin@gmail.com> 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context
|
||||
|
@ -6,3 +6,4 @@ a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6
|
||||
f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer <arrbee@arrbee.com> 1328653313 -0800 commit: Some whitespace only changes for testing purposes
|
||||
a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer <arrbee@arrbee.com> 1332734901 -0700 commit: added files in sub/sub
|
||||
217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer <arrbee@arrbee.com> 1332735555 -0700 commit: adding more files in sub for tree status
|
||||
24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah <yoram.harmelin@gmail.com> 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context
|
||||
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
x<01><>Kj1D<><44>)zol<6F>i<EFBFBD><69> _"hi<68>K2<4B>L<EFBFBD><4C>G!7Ȫ<05><><EFBFBD>J<EFBFBD>,<2C><><EFBFBD>E<EFBFBD>PX<50><58>D<EFBFBD><44>S<EFBFBD><53> ] /)<29><>}<7D><>/<2F><>Uw<55>R<EFBFBD><52>. <09>j<EFBFBD><6A><13><>p<EFBFBD><70><EFBFBD><EFBFBD>#<23><>#:?<3F><>:|<7C><>;<3B><>F9<46>܋<EFBFBD>r=_<0B><>)<29><>ơ<>N/<2F><>A[<5B><>l<EFBFBD><6C>!<21>q<EFBFBD><71>}<7D><><EFBFBD><15><Lfx4<78>H\<5C><>\<5C><>q֏cj<63><6A><EFBFBD><EFBFBD><04>T<EFBFBD>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user