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:
Vicent Marti 2010-12-03 18:01:30 +02:00
parent 86bfec39b5
commit 7d7cd8857a
15 changed files with 2222 additions and 1895 deletions

View File

@ -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

1834
src/odb.c

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;