mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-07 12:08:42 +00:00
Decouple storage from ODB logic
Comes with two default backends: loose object and packfiles. Signed-off-by: Vicent Marti <tanoku@gmail.com>
This commit is contained in:
parent
86bfec39b5
commit
7d7cd8857a
165
src/git/odb.h
165
src/git/odb.h
@ -17,16 +17,52 @@ GIT_BEGIN_DECL
|
||||
/** An open object database handle. */
|
||||
typedef struct git_odb git_odb;
|
||||
|
||||
/** A custom backend in an ODB */
|
||||
typedef struct git_odb_backend git_odb_backend;
|
||||
|
||||
/**
|
||||
* Open an object database for read/write access.
|
||||
* Create a new object database with no backends.
|
||||
*
|
||||
* Before the ODB can be used for read/writing, a custom database
|
||||
* backend must be manually added using `git_odb_add_backend()`
|
||||
*
|
||||
* @param out location to store the database pointer, if opened.
|
||||
* Set to NULL if the open failed.
|
||||
* @param objects_dir path of the database's "objects" directory.
|
||||
* @return GIT_SUCCESS if the database was created; otherwise an error
|
||||
* code describing why the open was not possible.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_new(git_odb **out);
|
||||
|
||||
/**
|
||||
* Create a new object database and automatically add
|
||||
* the two default backends:
|
||||
*
|
||||
* - git_odb_backend_loose: read and write loose object files
|
||||
* from disk, assuming `objects_dir` as the Objects folder
|
||||
*
|
||||
* - git_odb_backend_pack: read objects from packfiles,
|
||||
* assuming `objects_dir` as the Objects folder which
|
||||
* contains a 'pack/' folder with the corresponding data
|
||||
*
|
||||
* @param out location to store the database pointer, if opened.
|
||||
* Set to NULL if the open failed.
|
||||
* @param objects_dir path of the backends' "objects" directory.
|
||||
* @return GIT_SUCCESS if the database opened; otherwise an error
|
||||
* code describing why the open was not possible.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
|
||||
|
||||
/**
|
||||
* Add a custom backend to an existing Object DB
|
||||
*
|
||||
* Read <odb_backends.h> for more information.
|
||||
*
|
||||
* @param odb database to add the backend to
|
||||
* @paramm backend pointer to a git_odb_backend instance
|
||||
* @return 0 on sucess; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend);
|
||||
|
||||
/**
|
||||
* Close an open object database.
|
||||
* @param db database pointer to close. If NULL no action is taken.
|
||||
@ -76,7 +112,7 @@ GIT_EXTERN(int) git_odb_read(git_rawobj *out, git_odb *db, const git_oid *id);
|
||||
* are filled. The 'data' pointer will always be NULL.
|
||||
*
|
||||
* The raw object pointed by 'out' doesn't need to be manually
|
||||
* closed with git_obj_close().
|
||||
* closed with git_rawobj_close().
|
||||
*
|
||||
* @param out object descriptor to populate upon reading.
|
||||
* @param db database to search for the object in.
|
||||
@ -87,34 +123,6 @@ GIT_EXTERN(int) git_odb_read(git_rawobj *out, git_odb *db, const git_oid *id);
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_read_header(git_rawobj *out, git_odb *db, const git_oid *id);
|
||||
|
||||
/**
|
||||
* Read an object from the database using only pack files.
|
||||
*
|
||||
* If GIT_ENOTFOUND then out->data is set to NULL.
|
||||
*
|
||||
* @param out object descriptor to populate upon reading.
|
||||
* @param db database to search for the object in.
|
||||
* @param id identity of the object to read.
|
||||
* @return
|
||||
* - GIT_SUCCESS if the object was read.
|
||||
* - GIT_ENOTFOUND if the object is not in the database.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb__read_packed(git_rawobj *out, git_odb *db, const git_oid *id);
|
||||
|
||||
/**
|
||||
* Read an object from the database using only loose object files.
|
||||
*
|
||||
* If GIT_ENOTFOUND then out->data is set to NULL.
|
||||
*
|
||||
* @param out object descriptor to populate upon reading.
|
||||
* @param db database to search for the object in.
|
||||
* @param id identity of the object to read.
|
||||
* @return
|
||||
* - GIT_SUCCESS if the object was read.
|
||||
* - GIT_ENOTFOUND if the object is not in the database.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb__read_loose(git_rawobj *out, git_odb *db, const git_oid *id);
|
||||
|
||||
/**
|
||||
* Write an object to the database.
|
||||
*
|
||||
@ -128,47 +136,19 @@ GIT_EXTERN(int) git_odb__read_loose(git_rawobj *out, git_odb *db, const git_oid
|
||||
GIT_EXTERN(int) git_odb_write(git_oid *id, git_odb *db, git_rawobj *obj);
|
||||
|
||||
/**
|
||||
* Release all memory used by the obj structure.
|
||||
* Determine if the given object can be found in the object database.
|
||||
*
|
||||
* As a result of this call, obj->data will be set to NULL.
|
||||
*
|
||||
* If obj->data is already NULL, nothing happens.
|
||||
*
|
||||
* @param obj object descriptor to free.
|
||||
* @param db database to be searched for the given object.
|
||||
* @param id the object to search for.
|
||||
* @return
|
||||
* - true, if the object was found
|
||||
* - false, otherwise
|
||||
*/
|
||||
GIT_INLINE(void) git_obj_close(git_rawobj *obj)
|
||||
{
|
||||
free(obj->data);
|
||||
obj->data = NULL;
|
||||
}
|
||||
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
|
||||
|
||||
|
||||
/**
|
||||
* Convert an object type to it's string representation.
|
||||
*
|
||||
* The result is a pointer to a string in static memory and
|
||||
* should not be free()'ed.
|
||||
*
|
||||
* @param type object type to convert.
|
||||
* @return the corresponding string representation.
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_obj_type_to_string(git_otype type);
|
||||
|
||||
/**
|
||||
* Convert a string object type representation to it's git_otype.
|
||||
*
|
||||
* @param str the string to convert.
|
||||
* @return the corresponding git_otype.
|
||||
*/
|
||||
GIT_EXTERN(git_otype) git_obj_string_to_type(const char *str);
|
||||
|
||||
/**
|
||||
* Determine if the given git_otype is a valid loose object type.
|
||||
*
|
||||
* @param type object type to test.
|
||||
* @return true if the type represents a valid loose object type,
|
||||
* false otherwise.
|
||||
*/
|
||||
GIT_EXTERN(int) git_obj__loose_object_type(git_otype type);
|
||||
|
||||
/**
|
||||
* Determine the object-ID (sha1 hash) of the given git_rawobj.
|
||||
@ -182,18 +162,53 @@ GIT_EXTERN(int) git_obj__loose_object_type(git_otype type);
|
||||
* - GIT_SUCCESS if the object-ID was correctly determined.
|
||||
* - GIT_ERROR if the given object is malformed.
|
||||
*/
|
||||
GIT_EXTERN(int) git_obj_hash(git_oid *id, git_rawobj *obj);
|
||||
GIT_EXTERN(int) git_rawobj_hash(git_oid *id, git_rawobj *obj);
|
||||
|
||||
/**
|
||||
* Determine if the given object can be found in the object database.
|
||||
* Release all memory used by the obj structure.
|
||||
*
|
||||
* @param db database to be searched for the given object.
|
||||
* @param id the object to search for.
|
||||
* @return
|
||||
* - true, if the object was found
|
||||
* - false, otherwise
|
||||
* As a result of this call, obj->data will be set to NULL.
|
||||
*
|
||||
* If obj->data is already NULL, nothing happens.
|
||||
*
|
||||
* @param obj object descriptor to free.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
|
||||
GIT_INLINE(void) git_rawobj_close(git_rawobj *obj)
|
||||
{
|
||||
free(obj->data);
|
||||
obj->data = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert an object type to it's string representation.
|
||||
*
|
||||
* The result is a pointer to a string in static memory and
|
||||
* should not be free()'ed.
|
||||
*
|
||||
* @param type object type to convert.
|
||||
* @return the corresponding string representation.
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_otype_tostring(git_otype type);
|
||||
|
||||
/**
|
||||
* Convert a string object type representation to it's git_otype.
|
||||
*
|
||||
* @param str the string to convert.
|
||||
* @return the corresponding git_otype.
|
||||
*/
|
||||
GIT_EXTERN(git_otype) git_otype_fromstring(const char *str);
|
||||
|
||||
/**
|
||||
* Determine if the given git_otype is a valid loose object type.
|
||||
*
|
||||
* @param type object type to test.
|
||||
* @return true if the type represents a valid loose object type,
|
||||
* false otherwise.
|
||||
*/
|
||||
GIT_EXTERN(int) git_otype_is_loose(git_otype type);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
59
src/odb.h
59
src/odb.h
@ -1,22 +1,49 @@
|
||||
#ifndef INCLUDE_odb_h__
|
||||
#define INCLUDE_odb_h__
|
||||
|
||||
/** First 4 bytes of a pack-*.idx file header.
|
||||
*
|
||||
* Note this header exists only in idx v2 and later. The idx v1
|
||||
* file format does not have a magic sequence at the front, and
|
||||
* must be detected by the first four bytes *not* being this value
|
||||
* and the first 8 bytes matching the following expression:
|
||||
*
|
||||
* uint32_t *fanout = ... the file data at offset 0 ...
|
||||
* ntohl(fanout[0]) < ntohl(fanout[1])
|
||||
*
|
||||
* The value chosen here for PACK_TOC is such that the above
|
||||
* cannot be true for an idx v1 file.
|
||||
*/
|
||||
#define PACK_TOC 0xff744f63 /* -1tOc */
|
||||
#include <git/odb.h>
|
||||
#include <git/oid.h>
|
||||
|
||||
/** First 4 bytes of a pack-*.pack file header. */
|
||||
#define PACK_SIG 0x5041434b /* PACK */
|
||||
#include "vector.h"
|
||||
|
||||
struct git_odb {
|
||||
void *_internal;
|
||||
git_vector backends;
|
||||
};
|
||||
|
||||
struct git_odb_backend {
|
||||
git_odb *odb;
|
||||
|
||||
int priority;
|
||||
|
||||
int (* read)(
|
||||
git_rawobj *,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
int (* read_header)(
|
||||
git_rawobj *,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
int (* write)(
|
||||
git_oid *id,
|
||||
struct git_odb_backend *,
|
||||
git_rawobj *obj);
|
||||
|
||||
int (* exists)(
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
void (* free)(struct git_odb_backend *);
|
||||
|
||||
};
|
||||
|
||||
int git_odb__hash_obj(git_oid *id, char *hdr, size_t n, int *len, git_rawobj *obj);
|
||||
int git_odb__inflate_buffer(void *in, size_t inlen, void *out, size_t outlen);
|
||||
|
||||
|
||||
int git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir);
|
||||
int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir);
|
||||
|
||||
#endif
|
||||
|
||||
658
src/odb_loose.c
Normal file
658
src/odb_loose.c
Normal file
@ -0,0 +1,658 @@
|
||||
/*
|
||||
* 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 "git/zlib.h"
|
||||
#include "fileops.h"
|
||||
#include "hash.h"
|
||||
#include "odb.h"
|
||||
#include "delta-apply.h"
|
||||
|
||||
|
||||
typedef struct { /* object header data */
|
||||
git_otype type; /* object type */
|
||||
size_t size; /* object size */
|
||||
} obj_hdr;
|
||||
|
||||
typedef struct loose_backend {
|
||||
git_odb_backend parent;
|
||||
|
||||
int object_zlib_level; /** loose object zlib compression level. */
|
||||
int fsync_object_files; /** loose object file fsync flag. */
|
||||
char *objects_dir;
|
||||
} loose_backend;
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* MISCELANEOUS HELPER FUNCTIONS
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
static int make_temp_file(git_file *fd, char *tmp, size_t n, char *file)
|
||||
{
|
||||
char *template = "/tmp_obj_XXXXXX";
|
||||
size_t tmplen = strlen(template);
|
||||
int dirlen;
|
||||
|
||||
if ((dirlen = git__dirname(tmp, n, file)) < 0)
|
||||
return GIT_ERROR;
|
||||
|
||||
if ((dirlen + tmplen) >= n)
|
||||
return GIT_ERROR;
|
||||
|
||||
strcpy(tmp + dirlen, (dirlen) ? template : template + 1);
|
||||
|
||||
*fd = gitfo_mkstemp(tmp);
|
||||
if (*fd < 0 && dirlen) {
|
||||
/* create directory if it doesn't exist */
|
||||
tmp[dirlen] = '\0';
|
||||
if ((gitfo_exists(tmp) < 0) && gitfo_mkdir(tmp, 0755))
|
||||
return GIT_ERROR;
|
||||
/* try again */
|
||||
strcpy(tmp + dirlen, template);
|
||||
*fd = gitfo_mkstemp(tmp);
|
||||
}
|
||||
if (*fd < 0)
|
||||
return GIT_ERROR;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static size_t object_file_name(char *name, size_t n, char *dir, const git_oid *id)
|
||||
{
|
||||
size_t len = strlen(dir);
|
||||
|
||||
/* check length: 43 = 40 hex sha1 chars + 2 * '/' + '\0' */
|
||||
if (len+43 > n)
|
||||
return len+43;
|
||||
|
||||
/* the object dir: eg $GIT_DIR/objects */
|
||||
strcpy(name, dir);
|
||||
if (name[len-1] != '/')
|
||||
name[len++] = '/';
|
||||
|
||||
/* loose object filename: aa/aaa... (41 bytes) */
|
||||
git_oid_pathfmt(&name[len], id);
|
||||
name[len+41] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char *data = obj->data;
|
||||
size_t shift, size, used = 0;
|
||||
|
||||
if (obj->len == 0)
|
||||
return 0;
|
||||
|
||||
c = data[used++];
|
||||
hdr->type = (c >> 4) & 7;
|
||||
|
||||
size = c & 15;
|
||||
shift = 4;
|
||||
while (c & 0x80) {
|
||||
if (obj->len <= used)
|
||||
return 0;
|
||||
if (sizeof(size_t) * 8 <= shift)
|
||||
return 0;
|
||||
c = data[used++];
|
||||
size += (c & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
hdr->size = size;
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
static size_t get_object_header(obj_hdr *hdr, unsigned char *data)
|
||||
{
|
||||
char c, typename[10];
|
||||
size_t size, used = 0;
|
||||
|
||||
/*
|
||||
* type name string followed by space.
|
||||
*/
|
||||
while ((c = data[used]) != ' ') {
|
||||
typename[used++] = c;
|
||||
if (used >= sizeof(typename))
|
||||
return 0;
|
||||
}
|
||||
typename[used] = 0;
|
||||
if (used == 0)
|
||||
return 0;
|
||||
hdr->type = git_otype_fromstring(typename);
|
||||
used++; /* consume the space */
|
||||
|
||||
/*
|
||||
* length follows immediately in decimal (without
|
||||
* leading zeros).
|
||||
*/
|
||||
size = data[used++] - '0';
|
||||
if (size > 9)
|
||||
return 0;
|
||||
if (size) {
|
||||
while ((c = data[used]) != '\0') {
|
||||
size_t d = c - '0';
|
||||
if (d > 9)
|
||||
break;
|
||||
used++;
|
||||
size = size * 10 + d;
|
||||
}
|
||||
}
|
||||
hdr->size = size;
|
||||
|
||||
/*
|
||||
* the length must be followed by a zero byte
|
||||
*/
|
||||
if (data[used++] != '\0')
|
||||
return 0;
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* ZLIB RELATED FUNCTIONS
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
static void init_stream(z_stream *s, void *out, size_t len)
|
||||
{
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->next_out = out;
|
||||
s->avail_out = len;
|
||||
}
|
||||
|
||||
static void set_stream_input(z_stream *s, void *in, size_t len)
|
||||
{
|
||||
s->next_in = in;
|
||||
s->avail_in = len;
|
||||
}
|
||||
|
||||
static void set_stream_output(z_stream *s, void *out, size_t len)
|
||||
{
|
||||
s->next_out = out;
|
||||
s->avail_out = len;
|
||||
}
|
||||
|
||||
|
||||
static int start_inflate(z_stream *s, gitfo_buf *obj, void *out, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
init_stream(s, out, len);
|
||||
set_stream_input(s, obj->data, obj->len);
|
||||
|
||||
if ((status = inflateInit(s)) < Z_OK)
|
||||
return status;
|
||||
|
||||
return inflate(s, 0);
|
||||
}
|
||||
|
||||
static int finish_inflate(z_stream *s)
|
||||
{
|
||||
int status = Z_OK;
|
||||
|
||||
while (status == Z_OK)
|
||||
status = inflate(s, Z_FINISH);
|
||||
|
||||
inflateEnd(s);
|
||||
|
||||
if ((status != Z_STREAM_END) || (s->avail_in != 0))
|
||||
return GIT_ERROR;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int deflate_buf(z_stream *s, void *in, size_t len, int flush)
|
||||
{
|
||||
int status = Z_OK;
|
||||
|
||||
set_stream_input(s, in, len);
|
||||
while (status == Z_OK) {
|
||||
status = deflate(s, flush);
|
||||
if (s->avail_in == 0)
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int deflate_obj(gitfo_buf *buf, char *hdr, int hdrlen, git_rawobj *obj, int level)
|
||||
{
|
||||
z_stream zs;
|
||||
int status;
|
||||
size_t size;
|
||||
|
||||
assert(buf && !buf->data && hdr && obj);
|
||||
assert(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9));
|
||||
|
||||
buf->data = NULL;
|
||||
buf->len = 0;
|
||||
init_stream(&zs, NULL, 0);
|
||||
|
||||
if (deflateInit(&zs, level) < Z_OK)
|
||||
return GIT_ERROR;
|
||||
|
||||
size = deflateBound(&zs, hdrlen + obj->len);
|
||||
|
||||
if ((buf->data = git__malloc(size)) == NULL) {
|
||||
deflateEnd(&zs);
|
||||
return GIT_ERROR;
|
||||
}
|
||||
|
||||
set_stream_output(&zs, buf->data, size);
|
||||
|
||||
/* compress the header */
|
||||
status = deflate_buf(&zs, hdr, hdrlen, Z_NO_FLUSH);
|
||||
|
||||
/* if header compressed OK, compress the object */
|
||||
if (status == Z_OK)
|
||||
status = deflate_buf(&zs, obj->data, obj->len, Z_FINISH);
|
||||
|
||||
if (status != Z_STREAM_END) {
|
||||
deflateEnd(&zs);
|
||||
free(buf->data);
|
||||
buf->data = NULL;
|
||||
return GIT_ERROR;
|
||||
}
|
||||
|
||||
buf->len = zs.total_out;
|
||||
deflateEnd(&zs);
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int is_zlib_compressed_data(unsigned char *data)
|
||||
{
|
||||
unsigned int w;
|
||||
|
||||
w = ((unsigned int)(data[0]) << 8) + data[1];
|
||||
return data[0] == 0x78 && !(w % 31);
|
||||
}
|
||||
|
||||
static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
|
||||
{
|
||||
unsigned char *buf, *head = hb;
|
||||
size_t tail;
|
||||
|
||||
/*
|
||||
* allocate a buffer to hold the inflated data and copy the
|
||||
* initial sequence of inflated data from the tail of the
|
||||
* head buffer, if any.
|
||||
*/
|
||||
if ((buf = git__malloc(hdr->size + 1)) == NULL) {
|
||||
inflateEnd(s);
|
||||
return NULL;
|
||||
}
|
||||
tail = s->total_out - used;
|
||||
if (used > 0 && tail > 0) {
|
||||
if (tail > hdr->size)
|
||||
tail = hdr->size;
|
||||
memcpy(buf, head + used, tail);
|
||||
}
|
||||
used = tail;
|
||||
|
||||
/*
|
||||
* inflate the remainder of the object data, if any
|
||||
*/
|
||||
if (hdr->size < used)
|
||||
inflateEnd(s);
|
||||
else {
|
||||
set_stream_output(s, buf + used, hdr->size - used);
|
||||
if (finish_inflate(s)) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* At one point, there was a loose object format that was intended to
|
||||
* mimic the format used in pack-files. This was to allow easy copying
|
||||
* of loose object data into packs. This format is no longer used, but
|
||||
* we must still read it.
|
||||
*/
|
||||
static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
|
||||
{
|
||||
unsigned char *in, *buf;
|
||||
obj_hdr hdr;
|
||||
size_t len, used;
|
||||
|
||||
/*
|
||||
* read the object header, which is an (uncompressed)
|
||||
* binary encoding of the object type and size.
|
||||
*/
|
||||
if ((used = get_binary_object_header(&hdr, obj)) == 0)
|
||||
return GIT_ERROR;
|
||||
|
||||
if (!git_otype_is_loose(hdr.type))
|
||||
return GIT_ERROR;
|
||||
|
||||
/*
|
||||
* allocate a buffer and inflate the data into it
|
||||
*/
|
||||
buf = git__malloc(hdr.size + 1);
|
||||
if (!buf)
|
||||
return GIT_ERROR;
|
||||
|
||||
in = ((unsigned char *)obj->data) + used;
|
||||
len = obj->len - used;
|
||||
if (git_odb__inflate_buffer(in, len, buf, hdr.size)) {
|
||||
free(buf);
|
||||
return GIT_ERROR;
|
||||
}
|
||||
buf[hdr.size] = '\0';
|
||||
|
||||
out->data = buf;
|
||||
out->len = hdr.size;
|
||||
out->type = hdr.type;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* check for a pack-like loose object
|
||||
*/
|
||||
if (!is_zlib_compressed_data(obj->data))
|
||||
return inflate_packlike_loose_disk_obj(out, 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)
|
||||
return GIT_ERROR;
|
||||
|
||||
if ((used = get_object_header(&hdr, head)) == 0)
|
||||
return GIT_ERROR;
|
||||
|
||||
if (!git_otype_is_loose(hdr.type))
|
||||
return GIT_ERROR;
|
||||
|
||||
/*
|
||||
* allocate a buffer and inflate the object data into it
|
||||
* (including the initial sequence in the head buffer).
|
||||
*/
|
||||
if ((buf = inflate_tail(&zs, head, used, &hdr)) == NULL)
|
||||
return GIT_ERROR;
|
||||
buf[hdr.size] = '\0';
|
||||
|
||||
out->data = buf;
|
||||
out->len = hdr.size;
|
||||
out->type = hdr.type;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* ODB OBJECT READING & WRITING
|
||||
*
|
||||
* Backend for the public API; read headers and full objects
|
||||
* from the ODB. Write raw data to the ODB.
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
static int read_loose(git_rawobj *out, const char *loc)
|
||||
{
|
||||
int error;
|
||||
gitfo_buf obj = GITFO_BUF_INIT;
|
||||
|
||||
assert(out && loc);
|
||||
|
||||
out->data = NULL;
|
||||
out->len = 0;
|
||||
out->type = GIT_OBJ_BAD;
|
||||
|
||||
if (gitfo_read_file(&obj, loc) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
error = inflate_disk_obj(out, &obj);
|
||||
gitfo_free_buf(&obj);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int read_header_loose(git_rawobj *out, const char *loc)
|
||||
{
|
||||
int error = GIT_SUCCESS, z_return = Z_ERRNO, read_bytes;
|
||||
git_file fd;
|
||||
z_stream zs;
|
||||
obj_hdr header_obj;
|
||||
unsigned char raw_buffer[16], inflated_buffer[64];
|
||||
|
||||
assert(out && loc);
|
||||
|
||||
out->data = NULL;
|
||||
|
||||
if ((fd = gitfo_open(loc, O_RDONLY)) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
|
||||
|
||||
if (inflateInit(&zs) < Z_OK) {
|
||||
error = GIT_EZLIB;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
if ((read_bytes = read(fd, raw_buffer, sizeof(raw_buffer))) > 0) {
|
||||
set_stream_input(&zs, raw_buffer, read_bytes);
|
||||
z_return = inflate(&zs, 0);
|
||||
}
|
||||
} while (z_return == Z_OK);
|
||||
|
||||
if ((z_return != Z_STREAM_END && z_return != Z_BUF_ERROR)
|
||||
|| get_object_header(&header_obj, inflated_buffer) == 0
|
||||
|| git_otype_is_loose(header_obj.type) == 0) {
|
||||
error = GIT_EOBJCORRUPTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
out->len = header_obj.size;
|
||||
out->type = header_obj.type;
|
||||
|
||||
cleanup:
|
||||
finish_inflate(&zs);
|
||||
gitfo_close(fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int write_obj(gitfo_buf *buf, git_oid *id, loose_backend *backend)
|
||||
{
|
||||
char file[GIT_PATH_MAX];
|
||||
char temp[GIT_PATH_MAX];
|
||||
git_file fd;
|
||||
|
||||
if (object_file_name(file, sizeof(file), backend->objects_dir, id))
|
||||
return GIT_EOSERR;
|
||||
|
||||
if (make_temp_file(&fd, temp, sizeof(temp), file) < 0)
|
||||
return GIT_EOSERR;
|
||||
|
||||
if (gitfo_write(fd, buf->data, buf->len) < 0) {
|
||||
gitfo_close(fd);
|
||||
gitfo_unlink(temp);
|
||||
return GIT_EOSERR;
|
||||
}
|
||||
|
||||
if (backend->fsync_object_files)
|
||||
gitfo_fsync(fd);
|
||||
gitfo_close(fd);
|
||||
gitfo_chmod(temp, 0444);
|
||||
|
||||
if (gitfo_move_file(temp, file) < 0) {
|
||||
gitfo_unlink(temp);
|
||||
return GIT_EOSERR;
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int locate_object(char *object_location, loose_backend *backend, const git_oid *oid)
|
||||
{
|
||||
object_file_name(object_location, GIT_PATH_MAX, backend->objects_dir, oid);
|
||||
return gitfo_exists(object_location);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* LOOSE BACKEND PUBLIC API
|
||||
*
|
||||
* Implement the git_odb_backend API calls
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
int loose_backend__read_header(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
|
||||
{
|
||||
char object_path[GIT_PATH_MAX];
|
||||
|
||||
assert(obj && backend && oid);
|
||||
|
||||
if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
return read_header_loose(obj, object_path);
|
||||
}
|
||||
|
||||
|
||||
int loose_backend__read(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
|
||||
{
|
||||
char object_path[GIT_PATH_MAX];
|
||||
|
||||
assert(obj && backend && oid);
|
||||
|
||||
if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
return read_loose(obj, object_path);
|
||||
}
|
||||
|
||||
int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
|
||||
{
|
||||
char object_path[GIT_PATH_MAX];
|
||||
|
||||
assert(backend && oid);
|
||||
|
||||
return locate_object(object_path, (loose_backend *)backend, oid) == GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int loose_backend__write(git_oid *id, git_odb_backend *_backend, git_rawobj *obj)
|
||||
{
|
||||
char hdr[64];
|
||||
int hdrlen;
|
||||
gitfo_buf buf = GITFO_BUF_INIT;
|
||||
int error;
|
||||
loose_backend *backend;
|
||||
|
||||
assert(id && _backend && obj);
|
||||
|
||||
backend = (loose_backend *)_backend;
|
||||
|
||||
if ((error = git_odb__hash_obj(id, hdr, sizeof(hdr), &hdrlen, obj)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_odb_exists(_backend->odb, id))
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if ((error = deflate_obj(&buf, hdr, hdrlen, obj, backend->object_zlib_level)) < 0)
|
||||
return error;
|
||||
|
||||
error = write_obj(&buf, id, backend);
|
||||
|
||||
gitfo_free_buf(&buf);
|
||||
return error;
|
||||
}
|
||||
|
||||
void loose_backend__free(git_odb_backend *_backend)
|
||||
{
|
||||
loose_backend *backend;
|
||||
assert(_backend);
|
||||
backend = (loose_backend *)_backend;
|
||||
|
||||
free(backend->objects_dir);
|
||||
free(backend);
|
||||
}
|
||||
|
||||
int git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir)
|
||||
{
|
||||
loose_backend *backend;
|
||||
|
||||
backend = git__calloc(1, sizeof(loose_backend));
|
||||
if (backend == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
backend->objects_dir = git__strdup(objects_dir);
|
||||
if (backend->objects_dir == NULL) {
|
||||
free(backend);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
backend->object_zlib_level = Z_BEST_SPEED;
|
||||
backend->fsync_object_files = 0;
|
||||
|
||||
backend->parent.read = &loose_backend__read;
|
||||
backend->parent.read_header = &loose_backend__read_header;
|
||||
backend->parent.write = &loose_backend__write;
|
||||
backend->parent.exists = &loose_backend__exists;
|
||||
backend->parent.free = &loose_backend__free;
|
||||
|
||||
backend->parent.priority = 2; /* higher than packfiles */
|
||||
|
||||
*backend_out = (git_odb_backend *)backend;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
1207
src/odb_pack.c
Normal file
1207
src/odb_pack.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -445,7 +445,7 @@ void git_object__source_close(git_object *object)
|
||||
assert(object);
|
||||
|
||||
if (object->source.open) {
|
||||
git_obj_close(&object->source.raw);
|
||||
git_rawobj_close(&object->source.raw);
|
||||
object->source.open = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ int git_tag__writeback(git_tag *tag, git_odb_source *src)
|
||||
return GIT_EMISSINGOBJDATA;
|
||||
|
||||
git__write_oid(src, "object", git_object_id(tag->target));
|
||||
git__source_printf(src, "type %s\n", git_obj_type_to_string(tag->type));
|
||||
git__source_printf(src, "type %s\n", git_otype_tostring(tag->type));
|
||||
git__source_printf(src, "tag %s\n", tag->tag_name);
|
||||
git_person__write(src, "tagger", tag->tagger);
|
||||
|
||||
|
||||
@ -3,48 +3,48 @@
|
||||
#include <git/odb.h>
|
||||
|
||||
BEGIN_TEST(type_to_string)
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BAD), ""));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT1), ""));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_COMMIT), "commit"));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TREE), "tree"));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BLOB), "blob"));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TAG), "tag"));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT2), ""));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_REF_DELTA), "REF_DELTA"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_BAD), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ__EXT1), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_COMMIT), "commit"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_TREE), "tree"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_BLOB), "blob"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_TAG), "tag"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ__EXT2), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_OFS_DELTA), "OFS_DELTA"));
|
||||
must_be_true(!strcmp(git_otype_tostring(GIT_OBJ_REF_DELTA), "REF_DELTA"));
|
||||
|
||||
must_be_true(!strcmp(git_obj_type_to_string(-2), ""));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(8), ""));
|
||||
must_be_true(!strcmp(git_obj_type_to_string(1234), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(-2), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(8), ""));
|
||||
must_be_true(!strcmp(git_otype_tostring(1234), ""));
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(string_to_type)
|
||||
must_be_true(git_obj_string_to_type(NULL) == GIT_OBJ_BAD);
|
||||
must_be_true(git_obj_string_to_type("") == GIT_OBJ_BAD);
|
||||
must_be_true(git_obj_string_to_type("commit") == GIT_OBJ_COMMIT);
|
||||
must_be_true(git_obj_string_to_type("tree") == GIT_OBJ_TREE);
|
||||
must_be_true(git_obj_string_to_type("blob") == GIT_OBJ_BLOB);
|
||||
must_be_true(git_obj_string_to_type("tag") == GIT_OBJ_TAG);
|
||||
must_be_true(git_obj_string_to_type("OFS_DELTA") == GIT_OBJ_OFS_DELTA);
|
||||
must_be_true(git_obj_string_to_type("REF_DELTA") == GIT_OBJ_REF_DELTA);
|
||||
must_be_true(git_otype_fromstring(NULL) == GIT_OBJ_BAD);
|
||||
must_be_true(git_otype_fromstring("") == GIT_OBJ_BAD);
|
||||
must_be_true(git_otype_fromstring("commit") == GIT_OBJ_COMMIT);
|
||||
must_be_true(git_otype_fromstring("tree") == GIT_OBJ_TREE);
|
||||
must_be_true(git_otype_fromstring("blob") == GIT_OBJ_BLOB);
|
||||
must_be_true(git_otype_fromstring("tag") == GIT_OBJ_TAG);
|
||||
must_be_true(git_otype_fromstring("OFS_DELTA") == GIT_OBJ_OFS_DELTA);
|
||||
must_be_true(git_otype_fromstring("REF_DELTA") == GIT_OBJ_REF_DELTA);
|
||||
|
||||
must_be_true(git_obj_string_to_type("CoMmIt") == GIT_OBJ_BAD);
|
||||
must_be_true(git_obj_string_to_type("hohoho") == GIT_OBJ_BAD);
|
||||
must_be_true(git_otype_fromstring("CoMmIt") == GIT_OBJ_BAD);
|
||||
must_be_true(git_otype_fromstring("hohoho") == GIT_OBJ_BAD);
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(loose_object)
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_BAD) == 0);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ__EXT1) == 0);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_COMMIT) == 1);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_TREE) == 1);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_BLOB) == 1);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_TAG) == 1);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ__EXT2) == 0);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_OFS_DELTA) == 0);
|
||||
must_be_true(git_obj__loose_object_type(GIT_OBJ_REF_DELTA) == 0);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_BAD) == 0);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ__EXT1) == 0);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_COMMIT) == 1);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_TREE) == 1);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_BLOB) == 1);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_TAG) == 1);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ__EXT2) == 0);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_OFS_DELTA) == 0);
|
||||
must_be_true(git_otype_is_loose(GIT_OBJ_REF_DELTA) == 0);
|
||||
|
||||
must_be_true(git_obj__loose_object_type(-2) == 0);
|
||||
must_be_true(git_obj__loose_object_type(8) == 0);
|
||||
must_be_true(git_obj__loose_object_type(1234) == 0);
|
||||
must_be_true(git_otype_is_loose(-2) == 0);
|
||||
must_be_true(git_otype_is_loose(8) == 0);
|
||||
must_be_true(git_otype_is_loose(1234) == 0);
|
||||
END_TEST
|
||||
|
||||
|
||||
@ -326,28 +326,28 @@ BEGIN_TEST(hash_junk)
|
||||
|
||||
/* invalid types: */
|
||||
junk_obj.data = some_data;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
|
||||
junk_obj.type = GIT_OBJ__EXT1;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
|
||||
junk_obj.type = GIT_OBJ__EXT2;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
|
||||
junk_obj.type = GIT_OBJ_OFS_DELTA;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
|
||||
junk_obj.type = GIT_OBJ_REF_DELTA;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
|
||||
/* data can be NULL only if len is zero: */
|
||||
junk_obj.type = GIT_OBJ_BLOB;
|
||||
junk_obj.data = NULL;
|
||||
must_pass(git_obj_hash(&id, &junk_obj));
|
||||
must_pass(git_rawobj_hash(&id, &junk_obj));
|
||||
must_be_true(git_oid_cmp(&id, &id_zero) == 0);
|
||||
|
||||
junk_obj.len = 1;
|
||||
must_fail(git_obj_hash(&id, &junk_obj));
|
||||
must_fail(git_rawobj_hash(&id, &junk_obj));
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(hash_commit)
|
||||
@ -355,7 +355,7 @@ BEGIN_TEST(hash_commit)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, commit_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &commit_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &commit_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -365,7 +365,7 @@ BEGIN_TEST(hash_tree)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, tree_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &tree_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &tree_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -375,7 +375,7 @@ BEGIN_TEST(hash_tag)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, tag_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &tag_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &tag_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -385,7 +385,7 @@ BEGIN_TEST(hash_zero)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, zero_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &zero_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &zero_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -395,7 +395,7 @@ BEGIN_TEST(hash_one)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, one_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &one_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &one_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -405,7 +405,7 @@ BEGIN_TEST(hash_two)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, two_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &two_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &two_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
@ -415,7 +415,7 @@ BEGIN_TEST(hash_some)
|
||||
|
||||
must_pass(git_oid_mkstr(&id1, some_id));
|
||||
|
||||
must_pass(git_obj_hash(&id2, &some_obj));
|
||||
must_pass(git_rawobj_hash(&id2, &some_obj));
|
||||
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
END_TEST
|
||||
|
||||
@ -532,10 +532,10 @@ BEGIN_TEST(read_loose_commit)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, commit.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &commit));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &commit));
|
||||
END_TEST
|
||||
@ -549,10 +549,10 @@ BEGIN_TEST(read_loose_tree)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, tree.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &tree));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &tree));
|
||||
END_TEST
|
||||
@ -566,10 +566,10 @@ BEGIN_TEST(read_loose_tag)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, tag.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &tag));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &tag));
|
||||
END_TEST
|
||||
@ -583,10 +583,10 @@ BEGIN_TEST(read_loose_zero)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, zero.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &zero));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &zero));
|
||||
END_TEST
|
||||
@ -600,10 +600,10 @@ BEGIN_TEST(read_loose_one)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, one.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &one));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &one));
|
||||
END_TEST
|
||||
@ -617,10 +617,10 @@ BEGIN_TEST(read_loose_two)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, two.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &two));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &two));
|
||||
END_TEST
|
||||
@ -634,10 +634,10 @@ BEGIN_TEST(read_loose_some)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, some.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &some));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &some));
|
||||
END_TEST
|
||||
|
||||
@ -533,10 +533,10 @@ BEGIN_TEST(read_loose_commit)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, commit.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &commit));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &commit));
|
||||
END_TEST
|
||||
@ -550,10 +550,10 @@ BEGIN_TEST(read_loose_tree)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, tree.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &tree));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &tree));
|
||||
END_TEST
|
||||
@ -567,10 +567,10 @@ BEGIN_TEST(read_loose_tag)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, tag.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &tag));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &tag));
|
||||
END_TEST
|
||||
@ -584,10 +584,10 @@ BEGIN_TEST(read_loose_zero)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, zero.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &zero));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &zero));
|
||||
END_TEST
|
||||
@ -601,10 +601,10 @@ BEGIN_TEST(read_loose_one)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, one.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &one));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &one));
|
||||
END_TEST
|
||||
@ -618,10 +618,10 @@ BEGIN_TEST(read_loose_two)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, two.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &two));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &two));
|
||||
END_TEST
|
||||
@ -635,10 +635,10 @@ BEGIN_TEST(read_loose_some)
|
||||
must_pass(git_odb_open(&db, odb_dir));
|
||||
must_pass(git_oid_mkstr(&id, some.id));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
must_pass(cmp_objects(&obj, &some));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(odb_dir, &some));
|
||||
END_TEST
|
||||
|
||||
@ -143,9 +143,9 @@ BEGIN_TEST(readpacked_test)
|
||||
|
||||
must_pass(git_oid_mkstr(&id, packed_objects[i]));
|
||||
must_be_true(git_odb_exists(db, &id) == 1);
|
||||
must_pass(git_odb__read_packed(&obj, db, &id));
|
||||
must_pass(git_odb_read(&obj, db, &id));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
}
|
||||
|
||||
git_odb_close(db);
|
||||
|
||||
@ -172,7 +172,7 @@ BEGIN_TEST(readheader_packed_test)
|
||||
must_be_true(obj.len == header.len);
|
||||
must_be_true(obj.type == header.type);
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
}
|
||||
|
||||
git_odb_close(db);
|
||||
@ -199,7 +199,7 @@ BEGIN_TEST(readheader_loose_test)
|
||||
must_be_true(obj.len == header.len);
|
||||
must_be_true(obj.type == header.type);
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
}
|
||||
|
||||
git_odb_close(db);
|
||||
|
||||
@ -414,10 +414,10 @@ BEGIN_TEST(write_commit)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&commit));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &commit_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&commit));
|
||||
END_TEST
|
||||
@ -435,10 +435,10 @@ BEGIN_TEST(write_tree)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&tree));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &tree_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&tree));
|
||||
END_TEST
|
||||
@ -456,10 +456,10 @@ BEGIN_TEST(write_tag)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&tag));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &tag_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&tag));
|
||||
END_TEST
|
||||
@ -477,10 +477,10 @@ BEGIN_TEST(write_zero)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&zero));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &zero_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&zero));
|
||||
END_TEST
|
||||
@ -498,10 +498,10 @@ BEGIN_TEST(write_one)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&one));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &one_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&one));
|
||||
END_TEST
|
||||
@ -519,10 +519,10 @@ BEGIN_TEST(write_two)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&two));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &two_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&two));
|
||||
END_TEST
|
||||
@ -540,10 +540,10 @@ BEGIN_TEST(write_some)
|
||||
must_be_true(git_oid_cmp(&id1, &id2) == 0);
|
||||
must_pass(check_object_files(&some));
|
||||
|
||||
must_pass(git_odb__read_loose(&obj, db, &id1));
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj, &some_obj));
|
||||
|
||||
git_obj_close(&obj);
|
||||
git_rawobj_close(&obj);
|
||||
git_odb_close(db);
|
||||
must_pass(remove_object_files(&some));
|
||||
END_TEST
|
||||
|
||||
@ -125,7 +125,7 @@ int remove_loose_object(const char *repository_folder, git_object *object)
|
||||
|
||||
int cmp_objects(git_rawobj *o, object_data *d)
|
||||
{
|
||||
if (o->type != git_obj_string_to_type(d->type))
|
||||
if (o->type != git_otype_fromstring(d->type))
|
||||
return -1;
|
||||
if (o->len != d->dlen)
|
||||
return -1;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user