mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 02:36:11 +00:00
Merge upstream/development
This commit is contained in:
commit
94711cad3b
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.c eol=lf
|
||||
*.h eol=lf
|
@ -39,7 +39,7 @@ Under Unix-like systems, like Linux, *BSD and Mac OS X, libgit2 expects `pthread
|
||||
they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
|
||||
for threading.
|
||||
|
||||
Additionally, he following libraries may be used as replacement for built-in functionality:
|
||||
Additionally, the following libraries may be used as replacement for built-in functionality:
|
||||
|
||||
* LibSSL **(optional)** <http://www.openssl.org/>
|
||||
|
||||
@ -88,6 +88,9 @@ The waf build system for libgit2 accepts the following flags:
|
||||
--with-sqlite
|
||||
Enable sqlite support.
|
||||
|
||||
--with-redis
|
||||
Enable redis support.
|
||||
|
||||
You can run `./waf --help` to see a full list of install options and
|
||||
targets.
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
#ifndef INCLUDE_git_git_h__
|
||||
#define INCLUDE_git_git_h__
|
||||
|
||||
#define LIBGIT2_VERSION "0.11.0"
|
||||
#define LIBGIT2_VERSION "0.12.0"
|
||||
#define LIBGIT2_VER_MAJOR 0
|
||||
#define LIBGIT2_VER_MINOR 11
|
||||
#define LIBGIT2_VER_MINOR 12
|
||||
#define LIBGIT2_VER_REVISION 0
|
||||
|
||||
#include "git2/common.h"
|
||||
|
@ -84,92 +84,6 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Operation completed successfully. */
|
||||
#define GIT_SUCCESS 0
|
||||
|
||||
/**
|
||||
* Operation failed, with unspecified reason.
|
||||
* This value also serves as the base error code; all other
|
||||
* error codes are subtracted from it such that all errors
|
||||
* are < 0, in typical POSIX C tradition.
|
||||
*/
|
||||
#define GIT_ERROR -1
|
||||
|
||||
/** Input was not a properly formatted Git object id. */
|
||||
#define GIT_ENOTOID (GIT_ERROR - 1)
|
||||
|
||||
/** Input does not exist in the scope searched. */
|
||||
#define GIT_ENOTFOUND (GIT_ERROR - 2)
|
||||
|
||||
/** Not enough space available. */
|
||||
#define GIT_ENOMEM (GIT_ERROR - 3)
|
||||
|
||||
/** Consult the OS error information. */
|
||||
#define GIT_EOSERR (GIT_ERROR - 4)
|
||||
|
||||
/** The specified object is of invalid type */
|
||||
#define GIT_EOBJTYPE (GIT_ERROR - 5)
|
||||
|
||||
/** The specified object has its data corrupted */
|
||||
#define GIT_EOBJCORRUPTED (GIT_ERROR - 6)
|
||||
|
||||
/** The specified repository is invalid */
|
||||
#define GIT_ENOTAREPO (GIT_ERROR - 7)
|
||||
|
||||
/** The object or config variable type is invalid or doesn't match */
|
||||
#define GIT_EINVALIDTYPE (GIT_ERROR - 8)
|
||||
|
||||
/** The object cannot be written because it's missing internal data */
|
||||
#define GIT_EMISSINGOBJDATA (GIT_ERROR - 9)
|
||||
|
||||
/** The packfile for the ODB is corrupted */
|
||||
#define GIT_EPACKCORRUPTED (GIT_ERROR - 10)
|
||||
|
||||
/** Failed to acquire or release a file lock */
|
||||
#define GIT_EFLOCKFAIL (GIT_ERROR - 11)
|
||||
|
||||
/** The Z library failed to inflate/deflate an object's data */
|
||||
#define GIT_EZLIB (GIT_ERROR - 12)
|
||||
|
||||
/** The queried object is currently busy */
|
||||
#define GIT_EBUSY (GIT_ERROR - 13)
|
||||
|
||||
/** The index file is not backed up by an existing repository */
|
||||
#define GIT_EBAREINDEX (GIT_ERROR - 14)
|
||||
|
||||
/** The name of the reference is not valid */
|
||||
#define GIT_EINVALIDREFNAME (GIT_ERROR - 15)
|
||||
|
||||
/** The specified reference has its data corrupted */
|
||||
#define GIT_EREFCORRUPTED (GIT_ERROR - 16)
|
||||
|
||||
/** The specified symbolic reference is too deeply nested */
|
||||
#define GIT_ETOONESTEDSYMREF (GIT_ERROR - 17)
|
||||
|
||||
/** The pack-refs file is either corrupted or its format is not currently supported */
|
||||
#define GIT_EPACKEDREFSCORRUPTED (GIT_ERROR - 18)
|
||||
|
||||
/** The path is invalid */
|
||||
#define GIT_EINVALIDPATH (GIT_ERROR - 19)
|
||||
|
||||
/** The revision walker is empty; there are no more commits left to iterate */
|
||||
#define GIT_EREVWALKOVER (GIT_ERROR - 20)
|
||||
|
||||
/** The state of the reference is not valid */
|
||||
#define GIT_EINVALIDREFSTATE (GIT_ERROR - 21)
|
||||
|
||||
/** This feature has not been implemented yet */
|
||||
#define GIT_ENOTIMPLEMENTED (GIT_ERROR - 22)
|
||||
|
||||
/** A reference with this name already exists */
|
||||
#define GIT_EEXISTS (GIT_ERROR - 23)
|
||||
|
||||
/** The given integer literal is too large to be parsed */
|
||||
#define GIT_EOVERFLOW (GIT_ERROR - 24)
|
||||
|
||||
/** The given literal is not a valid number */
|
||||
#define GIT_ENOTNUM (GIT_ERROR - 25)
|
||||
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef struct {
|
||||
|
@ -25,6 +25,8 @@
|
||||
#ifndef INCLUDE_git_errors_h__
|
||||
#define INCLUDE_git_errors_h__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* @file git2/errors.h
|
||||
* @brief Git error handling routines and variables
|
||||
@ -33,8 +35,106 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef enum {
|
||||
GIT_SUCCESS = 0,
|
||||
GIT_ERROR = -1,
|
||||
|
||||
/** Input was not a properly formatted Git object id. */
|
||||
GIT_ENOTOID = -2,
|
||||
|
||||
/** Input does not exist in the scope searched. */
|
||||
GIT_ENOTFOUND = -3,
|
||||
|
||||
/** Not enough space available. */
|
||||
GIT_ENOMEM = -4,
|
||||
|
||||
/** Consult the OS error information. */
|
||||
GIT_EOSERR = -5,
|
||||
|
||||
/** The specified object is of invalid type */
|
||||
GIT_EOBJTYPE = -6,
|
||||
|
||||
/** The specified repository is invalid */
|
||||
GIT_ENOTAREPO = -7,
|
||||
|
||||
/** The object type is invalid or doesn't match */
|
||||
GIT_EINVALIDTYPE = -8,
|
||||
|
||||
/** The object cannot be written because it's missing internal data */
|
||||
GIT_EMISSINGOBJDATA = -9,
|
||||
|
||||
/** The packfile for the ODB is corrupted */
|
||||
GIT_EPACKCORRUPTED = -10,
|
||||
|
||||
/** Failed to acquire or release a file lock */
|
||||
GIT_EFLOCKFAIL = -11,
|
||||
|
||||
/** The Z library failed to inflate/deflate an object's data */
|
||||
GIT_EZLIB = -12,
|
||||
|
||||
/** The queried object is currently busy */
|
||||
GIT_EBUSY = -13,
|
||||
|
||||
/** The index file is not backed up by an existing repository */
|
||||
GIT_EBAREINDEX = -14,
|
||||
|
||||
/** The name of the reference is not valid */
|
||||
GIT_EINVALIDREFNAME = -15,
|
||||
|
||||
/** The specified reference has its data corrupted */
|
||||
GIT_EREFCORRUPTED = -16,
|
||||
|
||||
/** The specified symbolic reference is too deeply nested */
|
||||
GIT_ETOONESTEDSYMREF = -17,
|
||||
|
||||
/** The pack-refs file is either corrupted or its format is not currently supported */
|
||||
GIT_EPACKEDREFSCORRUPTED = -18,
|
||||
|
||||
/** The path is invalid */
|
||||
GIT_EINVALIDPATH = -19,
|
||||
|
||||
/** The revision walker is empty; there are no more commits left to iterate */
|
||||
GIT_EREVWALKOVER = -20,
|
||||
|
||||
/** The state of the reference is not valid */
|
||||
GIT_EINVALIDREFSTATE = -21,
|
||||
|
||||
/** This feature has not been implemented yet */
|
||||
GIT_ENOTIMPLEMENTED = -22,
|
||||
|
||||
/** A reference with this name already exists */
|
||||
GIT_EEXISTS = -23,
|
||||
|
||||
/** The given integer literal is too large to be parsed */
|
||||
GIT_EOVERFLOW = -24,
|
||||
|
||||
/** The given literal is not a valid number */
|
||||
GIT_ENOTNUM = -25,
|
||||
|
||||
/** Streaming error */
|
||||
GIT_ESTREAM = -26,
|
||||
|
||||
/** invalid arguments to function */
|
||||
GIT_EINVALIDARGS = -27,
|
||||
|
||||
/** The specified object has its data corrupted */
|
||||
GIT_EOBJCORRUPTED = -28,
|
||||
} git_error;
|
||||
|
||||
/**
|
||||
* Return a detailed error string with the latest error
|
||||
* that occurred in the library.
|
||||
* @return a string explaining the error
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_lasterror(void);
|
||||
|
||||
/**
|
||||
* strerror() for the Git library
|
||||
*
|
||||
* Get a string description for a given error code.
|
||||
* NOTE: This method will be eventually deprecated in favor
|
||||
* of the new `git_lasterror`.
|
||||
*
|
||||
* @param num The error code to explain
|
||||
* @return a string explaining the error code
|
||||
*/
|
||||
|
@ -232,10 +232,10 @@ GIT_EXTERN(int) git_index_append(git_index *index, const char *path, int stage);
|
||||
* @param source_entry new entry object
|
||||
* @return 0 on success, otherwise an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_index_apppend2(git_index *index, const git_index_entry *source_entry);
|
||||
GIT_EXTERN(int) git_index_append2(git_index *index, const git_index_entry *source_entry);
|
||||
|
||||
/**
|
||||
* Remove an entry from the index
|
||||
* Remove an entry from the index
|
||||
*
|
||||
* @param index an existing index object
|
||||
* @param position position of the entry to remove
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# undef GIT_TLS
|
||||
# define GIT_TLS
|
||||
|
||||
#elif defined(__GNUC__) || \
|
||||
defined(__SUNPRO_C) || \
|
||||
|
@ -53,7 +53,7 @@ int hiredis_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backe
|
||||
reply = redisCommand(backend->db, "HMGET %b %s %s", oid->id, GIT_OID_RAWSZ,
|
||||
"type", "size");
|
||||
|
||||
if (reply->type == REDIS_REPLY_ARRAY) {
|
||||
if (reply && reply->type == REDIS_REPLY_ARRAY) {
|
||||
if (reply->element[0]->type != REDIS_REPLY_NIL &&
|
||||
reply->element[0]->type != REDIS_REPLY_NIL) {
|
||||
*type_p = (git_otype) atoi(reply->element[0]->str);
|
||||
@ -83,7 +83,7 @@ int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_o
|
||||
reply = redisCommand(backend->db, "HMGET %b %s %s %s", oid->id, GIT_OID_RAWSZ,
|
||||
"type", "size", "data");
|
||||
|
||||
if (reply->type == REDIS_REPLY_ARRAY) {
|
||||
if (reply && reply->type == REDIS_REPLY_ARRAY) {
|
||||
if (reply->element[0]->type != REDIS_REPLY_NIL &&
|
||||
reply->element[1]->type != REDIS_REPLY_NIL &&
|
||||
reply->element[2]->type != REDIS_REPLY_NIL) {
|
||||
@ -118,7 +118,7 @@ int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) {
|
||||
found = 0;
|
||||
|
||||
reply = redisCommand(backend->db, "exists %b", oid->id, GIT_OID_RAWSZ);
|
||||
if (reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR)
|
||||
if (reply && reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR)
|
||||
found = 1;
|
||||
|
||||
|
||||
@ -144,7 +144,8 @@ int hiredis_backend__write(git_oid *id, git_odb_backend *_backend, const void *d
|
||||
"size %d "
|
||||
"data %b ", id->id, GIT_OID_RAWSZ,
|
||||
(int) type, len, data, len);
|
||||
error = reply->type == REDIS_REPLY_ERROR ? GIT_ERROR : GIT_SUCCESS;
|
||||
|
||||
error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_SUCCESS;
|
||||
|
||||
freeReplyObject(reply);
|
||||
return error;
|
||||
|
@ -62,7 +62,7 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
|
||||
git_odb_stream *stream;
|
||||
|
||||
if ((error = git_odb_open_wstream(&stream, repo->db, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to create blob. Can't open write stream");
|
||||
|
||||
stream->write(stream, buffer, len);
|
||||
|
||||
@ -81,7 +81,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
|
||||
git_odb_stream *stream;
|
||||
|
||||
if (repo->path_workdir == NULL)
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Failed to create blob. No workdir given");
|
||||
|
||||
git__joinpath(full_path, repo->path_workdir, path);
|
||||
|
||||
@ -106,7 +106,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
|
||||
if (read_len < 0) {
|
||||
gitfo_close(fd);
|
||||
stream->free(stream);
|
||||
return GIT_EOSERR;
|
||||
return git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
|
||||
}
|
||||
|
||||
stream->write(stream, buffer, read_len);
|
||||
|
84
src/cache.c
84
src/cache.c
@ -29,10 +29,7 @@
|
||||
#include "thread-utils.h"
|
||||
#include "cache.h"
|
||||
|
||||
#define GIT_CACHE_OPENADR 3
|
||||
|
||||
|
||||
void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
|
||||
int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -52,12 +49,15 @@ void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_p
|
||||
cache->free_obj = free_ptr;
|
||||
|
||||
cache->nodes = git__malloc((size + 1) * sizeof(cache_node));
|
||||
if (cache->nodes == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
for (i = 0; i < (size + 1); ++i) {
|
||||
git_mutex_init(&cache->nodes[i].lock);
|
||||
cache->nodes[i].ptr = NULL;
|
||||
cache->nodes[i].lru = 0;
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
void git_cache_free(git_cache *cache)
|
||||
@ -77,85 +77,53 @@ void git_cache_free(git_cache *cache)
|
||||
void *git_cache_get(git_cache *cache, const git_oid *oid)
|
||||
{
|
||||
const uint32_t *hash;
|
||||
size_t i, pos, found = 0;
|
||||
cache_node *node = NULL;
|
||||
void *result = NULL;
|
||||
|
||||
hash = (const uint32_t *)oid->id;
|
||||
node = &cache->nodes[hash[0] & cache->size_mask];
|
||||
|
||||
for (i = 0; !found && i < GIT_CACHE_OPENADR; ++i) {
|
||||
pos = hash[i] & cache->size_mask;
|
||||
node = &cache->nodes[pos];
|
||||
|
||||
git_mutex_lock(&node->lock);
|
||||
{
|
||||
if (node->ptr && git_cached_obj_compare(node->ptr, oid) == 0) {
|
||||
git_cached_obj_incref(node->ptr);
|
||||
node->lru = ++cache->lru_count;
|
||||
found = 1;
|
||||
}
|
||||
git_mutex_lock(&node->lock);
|
||||
{
|
||||
if (node->ptr && git_cached_obj_compare(node->ptr, oid) == 0) {
|
||||
git_cached_obj_incref(node->ptr);
|
||||
result = node->ptr;
|
||||
}
|
||||
git_mutex_unlock(&node->lock);
|
||||
}
|
||||
git_mutex_unlock(&node->lock);
|
||||
|
||||
|
||||
return found ? node->ptr : NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *git_cache_try_store(git_cache *cache, void *entry)
|
||||
{
|
||||
cache_node *nodes[GIT_CACHE_OPENADR], *lru_node;
|
||||
const uint32_t *hash;
|
||||
const git_oid *oid;
|
||||
size_t i;
|
||||
cache_node *node = NULL;
|
||||
|
||||
oid = &((git_cached_obj*)entry)->oid;
|
||||
hash = (const uint32_t *)oid->id;
|
||||
node = &cache->nodes[hash[0] & cache->size_mask];
|
||||
|
||||
/* increase the refcount on this object, because
|
||||
* the cache now owns it */
|
||||
git_cached_obj_incref(entry);
|
||||
git_mutex_lock(&node->lock);
|
||||
|
||||
for (i = 0; i < GIT_CACHE_OPENADR; ++i) {
|
||||
size_t pos = hash[i] & cache->size_mask;
|
||||
|
||||
nodes[i] = &cache->nodes[pos];
|
||||
git_mutex_lock(&nodes[i]->lock);
|
||||
}
|
||||
|
||||
lru_node = nodes[0];
|
||||
|
||||
for (i = 0; i < GIT_CACHE_OPENADR; ++i) {
|
||||
|
||||
if (nodes[i]->ptr == NULL) {
|
||||
nodes[i]->ptr = entry;
|
||||
nodes[i]->lru = ++cache->lru_count;
|
||||
break;
|
||||
} else if (git_cached_obj_compare(nodes[i]->ptr, oid) == 0) {
|
||||
git_cached_obj_decref(entry, cache->free_obj);
|
||||
entry = nodes[i]->ptr;
|
||||
nodes[i]->lru = ++cache->lru_count;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nodes[i]->lru < lru_node->lru)
|
||||
lru_node = nodes[i];
|
||||
}
|
||||
|
||||
if (i == GIT_CACHE_OPENADR) {
|
||||
void *old_entry = lru_node->ptr;
|
||||
assert(old_entry);
|
||||
|
||||
git_cached_obj_decref(old_entry, cache->free_obj);
|
||||
lru_node->ptr = entry;
|
||||
lru_node->lru = ++cache->lru_count;
|
||||
if (node->ptr == NULL) {
|
||||
node->ptr = entry;
|
||||
} else if (git_cached_obj_compare(node->ptr, oid) == 0) {
|
||||
git_cached_obj_decref(entry, cache->free_obj);
|
||||
entry = node->ptr;
|
||||
} else {
|
||||
git_cached_obj_decref(node->ptr, cache->free_obj);
|
||||
node->ptr = entry;
|
||||
}
|
||||
|
||||
/* increase the refcount again, because we are
|
||||
* returning it to the user */
|
||||
git_cached_obj_incref(entry);
|
||||
|
||||
for (i = 0; i < GIT_CACHE_OPENADR; ++i)
|
||||
git_mutex_unlock(&nodes[i]->lock);
|
||||
git_mutex_unlock(&node->lock);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ typedef struct {
|
||||
typedef struct {
|
||||
git_cached_obj *ptr;
|
||||
git_mutex lock;
|
||||
unsigned int lru;
|
||||
} cache_node;
|
||||
|
||||
typedef struct {
|
||||
@ -31,7 +30,7 @@ typedef struct {
|
||||
} git_cache;
|
||||
|
||||
|
||||
void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr);
|
||||
int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr);
|
||||
void git_cache_free(git_cache *cache);
|
||||
|
||||
void *git_cache_try_store(git_cache *cache, void *entry);
|
||||
|
@ -286,7 +286,7 @@ int commit_parse_buffer(git_commit *commit, const void *data, size_t len)
|
||||
|
||||
if (buffer < buffer_end) {
|
||||
const char *line_end;
|
||||
size_t message_len = buffer_end - buffer;
|
||||
size_t message_len;
|
||||
|
||||
/* Long message */
|
||||
message_len = buffer_end - buffer;
|
||||
|
@ -50,10 +50,14 @@ typedef SSIZE_T ssize_t;
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "util.h"
|
||||
#include "git2/errors.h"
|
||||
#include "thread-utils.h"
|
||||
#include "bswap.h"
|
||||
|
||||
#define GIT_PATH_MAX 4096
|
||||
extern int git__throw(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
extern int git__rethrow(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#endif /* INCLUDE_common_h__ */
|
||||
|
64
src/errors.c
64
src/errors.c
@ -1,6 +1,35 @@
|
||||
/*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* In addition to the permissions in the GNU General Public License,
|
||||
* the authors give you unlimited permission to link the compiled
|
||||
* version of this file into combinations with other programs,
|
||||
* and to distribute those combinations without any restriction
|
||||
* coming from the use of this file. (The General Public License
|
||||
* restrictions do apply in other respects; for example, they cover
|
||||
* modification of the file, and distribution when not linked into
|
||||
* a combined executable.)
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "git2/thread-utils.h" /* for GIT_TLS */
|
||||
#include "thread-utils.h" /* for GIT_TLS */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static GIT_TLS char g_last_error[1024];
|
||||
|
||||
static struct {
|
||||
int num;
|
||||
const char *str;
|
||||
@ -46,3 +75,38 @@ const char *git_strerror(int num)
|
||||
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
int git__rethrow(int error, const char *msg, ...)
|
||||
{
|
||||
char new_error[1024];
|
||||
char *old_error = NULL;
|
||||
|
||||
va_list va;
|
||||
|
||||
va_start(va, msg);
|
||||
vsnprintf(new_error, sizeof(new_error), msg, va);
|
||||
va_end(va);
|
||||
|
||||
old_error = strdup(g_last_error);
|
||||
snprintf(g_last_error, sizeof(g_last_error), "%s \n - %s", new_error, old_error);
|
||||
free(old_error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git__throw(int error, const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, msg);
|
||||
vsnprintf(g_last_error, sizeof(g_last_error), msg, va);
|
||||
va_end(va);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
const char *git_lasterror(void)
|
||||
{
|
||||
return g_last_error;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ int gitfo_mkdir_2file(const char *file_path)
|
||||
|
||||
error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to recursively build `%s` tree structure. Unable to parse parent folder name", file_path);
|
||||
|
||||
/* Does the containing folder exist? */
|
||||
if (gitfo_isdir(target_folder_path)) {
|
||||
@ -19,7 +19,7 @@ int gitfo_mkdir_2file(const char *file_path)
|
||||
/* Let's create the tree structure */
|
||||
error = gitfo_mkdir_recurs(target_folder_path, mode);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
return error; /* The callee already takes care of setting the correct error message. */
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
@ -164,19 +164,19 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
|
||||
|
||||
if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) {
|
||||
gitfo_close(fd);
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_ERROR, "Failed to read file `%s`. Either an error occured while calculating its size or the file is too large", path);
|
||||
}
|
||||
len = (size_t) size;
|
||||
|
||||
if ((buff = git__malloc(len + 1)) == NULL) {
|
||||
gitfo_close(fd);
|
||||
return GIT_ERROR;
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
if (gitfo_read(fd, buff, len) < 0) {
|
||||
gitfo_close(fd);
|
||||
free(buff);
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_ERROR, "Failed to read file `%s`", path);
|
||||
}
|
||||
buff[len] = '\0';
|
||||
|
||||
@ -197,13 +197,15 @@ void gitfo_free_buf(gitfo_buf *obj)
|
||||
|
||||
int gitfo_mv(const char *from, const char *to)
|
||||
{
|
||||
int error;
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
/*
|
||||
* Win32 POSIX compilance my ass. If the destination
|
||||
* file exists, the `rename` call fails. This is as
|
||||
* close as it gets with the Win32 API.
|
||||
*/
|
||||
return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
|
||||
error = MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
|
||||
#else
|
||||
/* Don't even try this on Win32 */
|
||||
if (!link(from, to)) {
|
||||
@ -214,16 +216,21 @@ int gitfo_mv(const char *from, const char *to)
|
||||
if (!rename(from, to))
|
||||
return GIT_SUCCESS;
|
||||
|
||||
return GIT_EOSERR;
|
||||
error = GIT_EOSERR;
|
||||
#endif
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__throw(error, "Failed to move file from `%s`to `%s`", from, to);
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int gitfo_mv_force(const char *from, const char *to)
|
||||
{
|
||||
if (gitfo_mkdir_2file(to) < GIT_SUCCESS)
|
||||
return GIT_EOSERR;
|
||||
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
|
||||
|
||||
return gitfo_mv(from, to);
|
||||
return gitfo_mv(from, to); /* The callee already takes care of setting the correct error message. */
|
||||
}
|
||||
|
||||
int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
|
||||
@ -338,7 +345,7 @@ int gitfo_dirent(
|
||||
struct dirent *de;
|
||||
|
||||
if (!wd_len || path_sz < wd_len + 2)
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_EINVALIDARGS, "Failed to process `%s` tree structure. Path is either empty or buffer size is too short", path);
|
||||
|
||||
while (path[wd_len - 1] == '/')
|
||||
wd_len--;
|
||||
@ -347,7 +354,7 @@ int gitfo_dirent(
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir)
|
||||
return GIT_EOSERR;
|
||||
return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path);
|
||||
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
size_t de_len;
|
||||
@ -364,14 +371,14 @@ int gitfo_dirent(
|
||||
de_len = strlen(de->d_name);
|
||||
if (path_sz < wd_len + de_len + 1) {
|
||||
closedir(dir);
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_ERROR, "Failed to process `%s` tree structure. Buffer size is too short", path);
|
||||
}
|
||||
|
||||
strcpy(path + wd_len, de->d_name);
|
||||
result = fn(arg, path);
|
||||
if (result < GIT_SUCCESS) {
|
||||
closedir(dir);
|
||||
return result;
|
||||
return result; /* The callee is reponsible for setting the correct error message */
|
||||
}
|
||||
if (result > 0) {
|
||||
closedir(dir);
|
||||
@ -399,7 +406,7 @@ int retrieve_path_root_offset(const char *path)
|
||||
if (*(path + offset) == '/')
|
||||
return offset;
|
||||
|
||||
return GIT_ERROR;
|
||||
return -1; /* Not a real error. Rather a signal than the path is not rooted */
|
||||
}
|
||||
|
||||
|
||||
@ -438,7 +445,11 @@ int gitfo_mkdir_recurs(const char *path, int mode)
|
||||
error = gitfo_mkdir(path, mode);
|
||||
|
||||
free(path_copy);
|
||||
return error;
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__throw(error, "Failed to recursively create `%s` tree structure", path);
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int retrieve_previous_path_component_start(const char *path)
|
||||
@ -484,7 +495,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
|
||||
if (root_path_offset < 0) {
|
||||
error = gitfo_getcwd(buffer_out, size);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
return error; /* The callee already takes care of setting the correct error message. */
|
||||
|
||||
len = strlen(buffer_out);
|
||||
buffer_out += len;
|
||||
@ -529,7 +540,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
|
||||
|
||||
/* Are we escaping out of the root dir? */
|
||||
if (len < 0)
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path escapes out of the root directory", path);
|
||||
|
||||
buffer_out = (char *)buffer_out_start + len;
|
||||
continue;
|
||||
@ -537,7 +548,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
|
||||
|
||||
/* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
|
||||
if (only_dots && segment_len > 0)
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path contains a segment with three `.` or more", path);
|
||||
|
||||
*buffer_out++ = '/';
|
||||
len++;
|
||||
@ -557,21 +568,21 @@ int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path)
|
||||
|
||||
/* Let's make sure the filename isn't empty nor a dot */
|
||||
if (path_len == 0 || (path_len == 1 && *path == '.'))
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path is either empty or equals `.`", path);
|
||||
|
||||
/* Let's make sure the filename doesn't end with "/", "/." or "/.." */
|
||||
for (i = 1; path_len > i && i < 4; i++) {
|
||||
if (!strncmp(path + path_len - i, pattern, i))
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
|
||||
}
|
||||
|
||||
error = gitfo_prettify_dir_path(buffer_out, size, path);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
return error; /* The callee already takes care of setting the correct error message. */
|
||||
|
||||
path_len = strlen(buffer_out);
|
||||
if (path_len < 2)
|
||||
return GIT_EINVALIDPATH;
|
||||
if (path_len < 2) /* TODO: Fixme. We should also take of detecting Windows rooted path (probably through usage of retrieve_path_root_offset) */
|
||||
return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
|
||||
|
||||
/* Remove the trailing slash */
|
||||
buffer_out[path_len - 1] = '\0';
|
||||
@ -616,11 +627,11 @@ int gitfo_getcwd(char *buffer_out, size_t size)
|
||||
#ifdef GIT_WIN32
|
||||
cwd_buffer = _getcwd(buffer_out, size);
|
||||
#else
|
||||
cwd_buffer = getcwd(buffer_out, size); //TODO: Fixme. Ensure the required headers are correctly included
|
||||
cwd_buffer = getcwd(buffer_out, size);
|
||||
#endif
|
||||
|
||||
if (cwd_buffer == NULL)
|
||||
return GIT_EOSERR;
|
||||
return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
|
||||
|
||||
posixify_path(buffer_out);
|
||||
|
||||
|
@ -421,7 +421,7 @@ int git_index_add2(git_index *index, const git_index_entry *source_entry)
|
||||
return index_insert(index, source_entry, 1);
|
||||
}
|
||||
|
||||
int git_index_apppend2(git_index *index, const git_index_entry *source_entry)
|
||||
int git_index_append2(git_index *index, const git_index_entry *source_entry)
|
||||
{
|
||||
return index_insert(index, source_entry, 0);
|
||||
}
|
||||
|
14
src/odb.c
14
src/odb.c
@ -221,7 +221,7 @@ static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
int backend_sort_cmp(const void *a, const void *b)
|
||||
static int backend_sort_cmp(const void *a, const void *b)
|
||||
{
|
||||
const backend_internal *backend_a = *(const backend_internal **)(a);
|
||||
const backend_internal *backend_b = *(const backend_internal **)(b);
|
||||
@ -234,15 +234,19 @@ int backend_sort_cmp(const void *a, const void *b)
|
||||
|
||||
int git_odb_new(git_odb **out)
|
||||
{
|
||||
int error;
|
||||
|
||||
git_odb *db = git__calloc(1, sizeof(*db));
|
||||
if (!db)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object);
|
||||
error = git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
|
||||
if ((error = git_vector_init(&db->backends, 4, backend_sort_cmp)) < GIT_SUCCESS) {
|
||||
free(db);
|
||||
return GIT_ENOMEM;
|
||||
return error;
|
||||
}
|
||||
|
||||
*out = db;
|
||||
@ -444,7 +448,7 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
|
||||
return error;
|
||||
|
||||
*len_p = object->raw.len;
|
||||
*type_p = object->raw.len;
|
||||
*type_p = object->raw.type;
|
||||
git_odb_object_close(object);
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,6 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
|
||||
{
|
||||
unsigned char head[64], *buf;
|
||||
z_stream zs;
|
||||
int z_status;
|
||||
obj_hdr hdr;
|
||||
size_t used;
|
||||
|
||||
@ -350,7 +349,7 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
|
||||
* inflate the initial part of the io buffer in order
|
||||
* to parse the object header (type and size).
|
||||
*/
|
||||
if ((z_status = start_inflate(&zs, obj, head, sizeof(head))) < Z_OK)
|
||||
if (start_inflate(&zs, obj, head, sizeof(head)) < Z_OK)
|
||||
return GIT_ERROR;
|
||||
|
||||
if ((used = get_object_header(&hdr, head)) == 0)
|
||||
|
33
src/refs.c
33
src/refs.c
@ -122,7 +122,8 @@ static int reference_create(
|
||||
else if (type == GIT_REF_OID)
|
||||
size = sizeof(reference_oid);
|
||||
else
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
return git__throw(GIT_EINVALIDARGS,
|
||||
"Invalid reference type. Use either GIT_REF_OID or GIT_REF_SYMBOLIC as type specifier");
|
||||
|
||||
reference = git__malloc(size);
|
||||
if (reference == NULL)
|
||||
@ -159,11 +160,9 @@ static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *re
|
||||
/* Determine the full path of the file */
|
||||
git__joinpath(path, repo_path, ref_name);
|
||||
|
||||
if (gitfo_stat(path, &st) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return GIT_EOBJCORRUPTED;
|
||||
if (gitfo_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
|
||||
return git__throw(GIT_ENOTFOUND,
|
||||
"Cannot read reference file '%s'", ref_name);
|
||||
|
||||
if (mtime)
|
||||
*mtime = st.st_mtime;
|
||||
@ -205,7 +204,8 @@ static int loose_update(git_reference *ref)
|
||||
else if (ref->type == GIT_REF_OID)
|
||||
error = loose_parse_oid(ref, &ref_file);
|
||||
else
|
||||
error = GIT_EINVALIDREFSTATE;
|
||||
error = git__throw(GIT_EOBJCORRUPTED,
|
||||
"Invalid reference type (%d) for loose reference", ref->type);
|
||||
|
||||
gitfo_free_buf(&ref_file);
|
||||
|
||||
@ -229,7 +229,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
ref_sym = (reference_symbolic *)ref;
|
||||
|
||||
if (file_content->len < (header_len + 1))
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Object too short");
|
||||
|
||||
/*
|
||||
* Assume we have already checked for the header
|
||||
@ -246,7 +247,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
/* remove newline at the end of file */
|
||||
eol = strchr(ref_sym->target, '\n');
|
||||
if (eol == NULL)
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Missing EOL");
|
||||
|
||||
*eol = '\0';
|
||||
if (eol[-1] == '\r')
|
||||
@ -257,6 +259,7 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
|
||||
{
|
||||
int error;
|
||||
reference_oid *ref_oid;
|
||||
char *buffer;
|
||||
|
||||
@ -265,17 +268,19 @@ static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
/* File format: 40 chars (OID) + newline */
|
||||
if (file_content->len < GIT_OID_HEXSZ + 1)
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Reference too short");
|
||||
|
||||
if (git_oid_mkstr(&ref_oid->oid, buffer) < GIT_SUCCESS)
|
||||
return GIT_EREFCORRUPTED;
|
||||
if ((error = git_oid_mkstr(&ref_oid->oid, buffer)) < GIT_SUCCESS)
|
||||
return git__rethrow(GIT_EOBJCORRUPTED, "Failed to parse loose reference.");
|
||||
|
||||
buffer = buffer + GIT_OID_HEXSZ;
|
||||
if (*buffer == '\r')
|
||||
buffer++;
|
||||
|
||||
if (*buffer != '\n')
|
||||
return GIT_EREFCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED,
|
||||
"Failed to parse loose reference. Missing EOL");
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
@ -387,7 +392,7 @@ static int loose_write(git_reference *ref)
|
||||
strcpy(ref_contents, GIT_SYMREF);
|
||||
strcat(ref_contents, ref_sym->target);
|
||||
} else {
|
||||
error = GIT_EINVALIDREFSTATE;
|
||||
error = git__throw(GIT_EOBJCORRUPTED, "Failed to write reference. Invalid reference type");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
@ -124,16 +124,16 @@ static int check_repository_dirs(git_repository *repo)
|
||||
char path_aux[GIT_PATH_MAX];
|
||||
|
||||
if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS)
|
||||
return GIT_ENOTAREPO;
|
||||
return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository);
|
||||
|
||||
/* Ensure GIT_OBJECT_DIRECTORY exists */
|
||||
if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS)
|
||||
return GIT_ENOTAREPO;
|
||||
return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb);
|
||||
|
||||
/* Ensure HEAD file exists */
|
||||
git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
|
||||
if (gitfo_exists(path_aux) < 0)
|
||||
return GIT_ENOTAREPO;
|
||||
return git__throw(GIT_ENOTAREPO, "HEAD file is missing");
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
@ -145,12 +145,12 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
|
||||
|
||||
/* Git directory name */
|
||||
if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0)
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path);
|
||||
|
||||
if (strcmp(buffer, DOT_GIT) == 0) {
|
||||
/* Path to working dir */
|
||||
if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0)
|
||||
return GIT_EINVALIDPATH;
|
||||
return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path);
|
||||
path_work_tree = buffer;
|
||||
}
|
||||
|
||||
@ -159,13 +159,19 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
|
||||
|
||||
static git_repository *repository_alloc()
|
||||
{
|
||||
int error;
|
||||
|
||||
git_repository *repo = git__malloc(sizeof(git_repository));
|
||||
if (!repo)
|
||||
return NULL;
|
||||
|
||||
memset(repo, 0x0, sizeof(git_repository));
|
||||
|
||||
git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
|
||||
error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
|
||||
if (error < GIT_SUCCESS) {
|
||||
free(repo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (git_repository__refcache_init(&repo->references) < GIT_SUCCESS) {
|
||||
free(repo);
|
||||
@ -177,7 +183,7 @@ static git_repository *repository_alloc()
|
||||
|
||||
static int init_odb(git_repository *repo)
|
||||
{
|
||||
return git_odb_open(&repo->db, repo->path_odb);
|
||||
return git_odb_open(&repo->db, repo->path_odb); /* TODO: Move odb.c to new error handling */
|
||||
}
|
||||
|
||||
int git_repository_open3(git_repository **repo_out,
|
||||
@ -192,7 +198,7 @@ int git_repository_open3(git_repository **repo_out,
|
||||
assert(repo_out);
|
||||
|
||||
if (object_database == NULL)
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_EINVALIDARGS, "Failed to open repository. `object_database` can't be null");
|
||||
|
||||
repo = repository_alloc();
|
||||
if (repo == NULL)
|
||||
@ -218,7 +224,7 @@ int git_repository_open3(git_repository **repo_out,
|
||||
|
||||
cleanup:
|
||||
git_repository_free(repo);
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to open repository");
|
||||
}
|
||||
|
||||
|
||||
@ -259,7 +265,7 @@ int git_repository_open2(git_repository **repo_out,
|
||||
|
||||
cleanup:
|
||||
git_repository_free(repo);
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to open repository");
|
||||
}
|
||||
|
||||
int git_repository_open(git_repository **repo_out, const char *path)
|
||||
@ -290,7 +296,7 @@ int git_repository_open(git_repository **repo_out, const char *path)
|
||||
|
||||
cleanup:
|
||||
git_repository_free(repo);
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to open repository");
|
||||
}
|
||||
|
||||
void git_repository_free(git_repository *repo)
|
||||
@ -322,7 +328,7 @@ int git_repository_index(git_index **index_out, git_repository *repo)
|
||||
assert(index_out && repo);
|
||||
|
||||
if (repo->index == NULL) {
|
||||
error = git_index_open_inrepo(&repo->index, repo);
|
||||
error = git_index_open_inrepo(&repo->index, repo); /* TODO: move index.c to new error handling */
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
@ -349,7 +355,7 @@ static int repo_init_reinit(repo_init *results)
|
||||
static int repo_init_createhead(git_repository *repo)
|
||||
{
|
||||
git_reference *head_reference;
|
||||
return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE);
|
||||
return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE); /* TODO: finalize moving refs.c to new error handling */
|
||||
}
|
||||
|
||||
static int repo_init_check_head_existence(char * repository_path)
|
||||
@ -363,6 +369,7 @@ static int repo_init_check_head_existence(char * repository_path)
|
||||
static int repo_init_structure(repo_init *results)
|
||||
{
|
||||
const int mode = 0755; /* or 0777 ? */
|
||||
int error;
|
||||
|
||||
char temp_path[GIT_PATH_MAX];
|
||||
char *git_dir = results->path_repository;
|
||||
@ -372,23 +379,27 @@ static int repo_init_structure(repo_init *results)
|
||||
|
||||
/* Creates the '/objects/info/' directory */
|
||||
git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
|
||||
if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS)
|
||||
return GIT_ERROR;
|
||||
error = gitfo_mkdir_recurs(temp_path, mode);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
/* Creates the '/objects/pack/' directory */
|
||||
git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
|
||||
if (gitfo_mkdir(temp_path, mode))
|
||||
return GIT_ERROR;
|
||||
error = gitfo_mkdir(temp_path, mode);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__throw(error, "Unable to create `%s` folder", temp_path);
|
||||
|
||||
/* Creates the '/refs/heads/' directory */
|
||||
git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR);
|
||||
if (gitfo_mkdir_recurs(temp_path, mode))
|
||||
return GIT_ERROR;
|
||||
error = gitfo_mkdir_recurs(temp_path, mode);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
/* Creates the '/refs/tags/' directory */
|
||||
git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR);
|
||||
if (gitfo_mkdir(temp_path, mode))
|
||||
return GIT_ERROR;
|
||||
error = gitfo_mkdir(temp_path, mode);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__throw(error, "Unable to create `%s` folder", temp_path);
|
||||
|
||||
/* TODO: what's left? templates? */
|
||||
|
||||
@ -467,7 +478,7 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
|
||||
cleanup:
|
||||
free(results.path_repository);
|
||||
git_repository_free(repo);
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to (re)init the repository `%s`", path);
|
||||
}
|
||||
|
||||
int git_repository_is_empty(git_repository *repo)
|
||||
@ -477,10 +488,10 @@ int git_repository_is_empty(git_repository *repo)
|
||||
|
||||
error = git_reference_lookup(&head, repo, "HEAD");
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
return git__throw(error, "Failed to determine the emptiness of the repository. An error occured while retrieving the HEAD reference");
|
||||
|
||||
if (git_reference_type(head) != GIT_REF_SYMBOLIC)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to determine the emptiness of the repository. HEAD is probably in detached state");
|
||||
|
||||
return git_reference_resolve(&branch, head) == GIT_SUCCESS ? 0 : 1;
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
|
||||
git_oid oid;
|
||||
|
||||
if (git_oid_mkstr(&oid, (char *)buffer + STRLEN("parent ")) < GIT_SUCCESS)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Parent object is corrupted");
|
||||
|
||||
commit->parents[i] = commit_lookup(walk, &oid);
|
||||
if (commit->parents[i] == NULL)
|
||||
@ -222,14 +222,14 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
|
||||
commit->out_degree = (unsigned short)parents;
|
||||
|
||||
if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Object is corrupted");
|
||||
|
||||
buffer = memchr(buffer, '>', buffer_end - buffer);
|
||||
if (buffer == NULL)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Can't find author");
|
||||
|
||||
if (git__strtol32(&commit_time, (char *)buffer + 2, NULL, 10) < GIT_SUCCESS)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Can't parse commit time");
|
||||
|
||||
commit->time = (time_t)commit_time;
|
||||
commit->parsed = 1;
|
||||
@ -245,11 +245,11 @@ static int commit_parse(git_revwalk *walk, commit_object *commit)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if ((error = git_odb_read(&obj, walk->repo->db, &commit->oid)) < GIT_SUCCESS)
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to parse commit. Can't read object");
|
||||
|
||||
if (obj->raw.type != GIT_OBJ_COMMIT) {
|
||||
git_odb_object_close(obj);
|
||||
return GIT_EOBJTYPE;
|
||||
return git__throw(GIT_EOBJTYPE, "Failed to parse commit. Object is no commit object");
|
||||
}
|
||||
|
||||
error = commit_quick_parse(walk, commit, &obj->raw);
|
||||
@ -305,7 +305,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
|
||||
|
||||
commit = commit_lookup(walk, oid);
|
||||
if (commit == NULL)
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Failed to push commit. Object not found");
|
||||
|
||||
commit->uninteresting = uninteresting;
|
||||
|
||||
|
@ -115,22 +115,22 @@ static int parse_timezone_offset(const char *buffer, long *offset_out)
|
||||
}
|
||||
|
||||
if (offset_start[0] != '-' && offset_start[0] != '+')
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It doesn't start with '+' or '-'");
|
||||
|
||||
if (git__strtol32(&dec_offset, offset_start + 1, &offset_end, 10) < GIT_SUCCESS)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It isn't a number");
|
||||
|
||||
if (offset_end - offset_start != 5)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Invalid length");
|
||||
|
||||
hours = dec_offset / 100;
|
||||
mins = dec_offset % 100;
|
||||
|
||||
if (hours > 14) // see http://www.worldtimezone.com/faq.html
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Hour value too large");;
|
||||
|
||||
if (mins > 59)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Minute value too large");
|
||||
|
||||
offset = (hours * 60) + mins;
|
||||
|
||||
@ -157,19 +157,19 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
|
||||
line_end = memchr(buffer, '\n', buffer_end - buffer);
|
||||
if (!line_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline found");;
|
||||
|
||||
if (buffer + (header_len + 1) > line_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
|
||||
|
||||
if (memcmp(buffer, header, header_len) != 0)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
|
||||
|
||||
buffer += header_len;
|
||||
|
||||
/* Parse name */
|
||||
if ((name_end = memchr(buffer, '<', buffer_end - buffer)) == NULL)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail start");
|
||||
|
||||
name_length = name_end - buffer - 1;
|
||||
sig->name = git__malloc(name_length + 1);
|
||||
@ -181,11 +181,11 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
buffer = name_end + 1;
|
||||
|
||||
if (buffer >= line_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
|
||||
|
||||
/* Parse email */
|
||||
if ((email_end = memchr(buffer, '>', buffer_end - buffer)) == NULL)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail end");
|
||||
|
||||
email_length = email_end - buffer;
|
||||
sig->email = git__malloc(email_length + 1);
|
||||
@ -197,10 +197,10 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
buffer = email_end + 1;
|
||||
|
||||
if (buffer >= line_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
|
||||
|
||||
if (git__strtol32(&time, buffer, &buffer, 10) < GIT_SUCCESS)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Timestamp isn't a number");
|
||||
|
||||
sig->when.time = (time_t)time;
|
||||
|
||||
|
19
src/tag.c
19
src/tag.c
@ -90,13 +90,13 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
|
||||
int error;
|
||||
|
||||
if ((error = git__parse_oid(&tag->target, &buffer, buffer_end, "object ")) < 0)
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to parse tag. Object field invalid");
|
||||
|
||||
if (buffer + 5 >= buffer_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
|
||||
|
||||
if (memcmp(buffer, "type ", 5) != 0)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Type field not found");
|
||||
buffer += 5;
|
||||
|
||||
tag->type = GIT_OBJ_BAD;
|
||||
@ -105,7 +105,7 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
|
||||
size_t type_length = strlen(tag_types[i]);
|
||||
|
||||
if (buffer + type_length >= buffer_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
|
||||
|
||||
if (memcmp(buffer, tag_types[i], type_length) == 0) {
|
||||
tag->type = i;
|
||||
@ -115,18 +115,19 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
|
||||
}
|
||||
|
||||
if (tag->type == GIT_OBJ_BAD)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Invalid object type");
|
||||
|
||||
if (buffer + 4 >= buffer_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
|
||||
|
||||
if (memcmp(buffer, "tag ", 4) != 0)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Tag field not found");
|
||||
|
||||
buffer += 4;
|
||||
|
||||
search = memchr(buffer, '\n', buffer_end - buffer);
|
||||
if (search == NULL)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
|
||||
|
||||
text_len = search - buffer;
|
||||
|
||||
@ -218,7 +219,7 @@ static int tag_create(
|
||||
}
|
||||
|
||||
if (!git_odb_exists(repo->db, target))
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Failed to create tag. Object to tag doesn't exist");
|
||||
|
||||
/* Try to find out what the type is */
|
||||
if (target_type == GIT_OBJ_ANY) {
|
||||
|
14
src/tree.c
14
src/tree.c
@ -151,15 +151,15 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
|
||||
return GIT_ENOMEM;
|
||||
|
||||
if (git__strtol32((long *)&entry->attr, buffer, &buffer, 8) < GIT_SUCCESS)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Can't parse attributes");
|
||||
|
||||
if (*buffer++ != ' ') {
|
||||
error = GIT_EOBJCORRUPTED;
|
||||
error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted");
|
||||
break;
|
||||
}
|
||||
|
||||
if (memchr(buffer, 0, buffer_end - buffer) == NULL) {
|
||||
error = GIT_EOBJCORRUPTED;
|
||||
error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ int git_tree_create_fromindex(git_oid *oid, git_index *index)
|
||||
int error;
|
||||
|
||||
if (index->repository == NULL)
|
||||
return GIT_EBAREINDEX;
|
||||
return git__throw(GIT_EBAREINDEX, "Failed to create tree. The index file is not backed up by an existing repository");
|
||||
|
||||
error = write_index(oid, index, "", 0, 0, git_index_entrycount(index));
|
||||
return (error < GIT_SUCCESS) ? error : GIT_SUCCESS;
|
||||
@ -343,7 +343,7 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
|
||||
assert(bld && id && filename);
|
||||
|
||||
if (!valid_attributes(attributes))
|
||||
return GIT_ERROR;
|
||||
return git__throw(GIT_ERROR, "Failed to insert entry. Invalid atrributes");
|
||||
|
||||
if ((pos = git_vector_bsearch2(&bld->entries, entry_search_cmp, filename)) != GIT_ENOTFOUND) {
|
||||
entry = git_vector_get(&bld->entries, pos);
|
||||
@ -400,7 +400,7 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
|
||||
git_tree_entry *remove_ptr = (git_tree_entry *)git_treebuilder_get(bld, filename);
|
||||
|
||||
if (remove_ptr == NULL || remove_ptr->removed)
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Failed to remove entry. File isn't in the tree");
|
||||
|
||||
remove_ptr->removed = 1;
|
||||
bld->entry_count--;
|
||||
@ -431,7 +431,7 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
|
||||
}
|
||||
|
||||
if ((error = git_odb_open_wstream(&stream, git_repository_database(repo), size, GIT_OBJ_TREE)) < GIT_SUCCESS)
|
||||
return error;
|
||||
return git__rethrow(error, "Failed to write tree. Can't open write stream");
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *entry = bld->entries.contents[i];
|
||||
|
44
src/util.h
44
src/util.h
@ -6,17 +6,41 @@
|
||||
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
|
||||
|
||||
/*
|
||||
* Don't wrap malloc/calloc.
|
||||
* Use the default versions in glibc, and make
|
||||
* sure that any methods that allocate memory
|
||||
* return a GIT_ENOMEM error when allocation
|
||||
* fails.
|
||||
* Custom memory allocation wrappers
|
||||
* that set error code and error message
|
||||
* on allocation failure
|
||||
*/
|
||||
#define git__malloc malloc
|
||||
#define git__calloc calloc
|
||||
#define git__realloc realloc
|
||||
#define git__strdup strdup
|
||||
#define git__strndup strndup
|
||||
GIT_INLINE(void *) git__malloc(size_t len)
|
||||
{
|
||||
void *ptr = malloc(len);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize)
|
||||
{
|
||||
void *ptr = calloc(nelem, elsize);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)elsize);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(char *) git__strdup(const char *str)
|
||||
{
|
||||
char *ptr = strdup(str);
|
||||
if (!ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to duplicate string");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *new_ptr = realloc(ptr, size);
|
||||
if (!new_ptr)
|
||||
git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)size);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
extern int git__fmt(char *, size_t, const char *, ...)
|
||||
GIT_FORMAT_PRINTF(3, 4);
|
||||
|
11
src/vector.c
11
src/vector.c
@ -106,7 +106,7 @@ int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *ke
|
||||
|
||||
/* need comparison function to sort the vector */
|
||||
if (v->_cmp == NULL)
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Can't sort vector. No comparison function set");
|
||||
|
||||
git_vector_sort(v);
|
||||
|
||||
@ -114,7 +114,7 @@ int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *ke
|
||||
if (find != NULL)
|
||||
return (int)(find - v->contents);
|
||||
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Can't find element");
|
||||
}
|
||||
|
||||
int git_vector_search2(git_vector *v, git_vector_cmp key_lookup, const void *key)
|
||||
@ -128,7 +128,7 @@ int git_vector_search2(git_vector *v, git_vector_cmp key_lookup, const void *key
|
||||
return i;
|
||||
}
|
||||
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Can't find element");
|
||||
}
|
||||
|
||||
static int strict_comparison(const void *a, const void *b)
|
||||
@ -143,9 +143,6 @@ int git_vector_search(git_vector *v, const void *entry)
|
||||
|
||||
int git_vector_bsearch(git_vector *v, const void *key)
|
||||
{
|
||||
if (v->_cmp == NULL)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
return git_vector_bsearch2(v, v->_cmp, key);
|
||||
}
|
||||
|
||||
@ -156,7 +153,7 @@ int git_vector_remove(git_vector *v, unsigned int idx)
|
||||
assert(v);
|
||||
|
||||
if (idx >= v->length || v->length == 0)
|
||||
return GIT_ENOTFOUND;
|
||||
return git__throw(GIT_ENOTFOUND, "Can't remove element. Index out of bounds");
|
||||
|
||||
for (i = idx; i < v->length - 1; ++i)
|
||||
v->contents[i] = v->contents[i + 1];
|
||||
|
@ -48,16 +48,15 @@ int pthread_join(pthread_t thread, void **value_ptr)
|
||||
int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT mutex,
|
||||
const pthread_mutexattr_t *GIT_RESTRICT GIT_UNUSED(mutexattr))
|
||||
{
|
||||
GIT_UNUSED_ARG(mutexattr);
|
||||
GIT_UNUSED_ARG(mutexattr);
|
||||
InitializeCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
{
|
||||
int ret;
|
||||
ret = CloseHandle(mutex);
|
||||
return -(!ret);
|
||||
DeleteCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
|
@ -292,7 +292,7 @@ BEGIN_TEST(create2, "create a new OID reference")
|
||||
/* Similar test with a fresh new repository */
|
||||
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
|
||||
|
||||
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
|
||||
must_pass(git_reference_lookup(&looked_up_ref, repo2, new_head));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
|
||||
|
||||
close_temp_repo(repo2);
|
||||
|
Loading…
Reference in New Issue
Block a user