Commit 4cba39ac by Vicent Martí

Merge pull request #615 from benstraub/port-all-tests-to-clar

Port all tests to clar
parents 5afe95d2 b1731215
......@@ -51,8 +51,7 @@ SET(INSTALL_INC include CACHE PATH "Where to install headers to.")
# Build options
OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
OPTION (THREADSAFE "Build libgit2 as threadsafe" OFF)
OPTION (BUILD_TESTS "Build Tests" ON)
OPTION (BUILD_CLAR "Build Tests using the Clar suite" OFF)
OPTION (BUILD_CLAR "Build Tests using the Clar suite" ON)
OPTION (TAGS "Generate tags" OFF)
# Platform specific compilation flags
......@@ -64,10 +63,11 @@ IF (MSVC)
IF (STDCALL)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gz")
ENDIF ()
# TODO: bring back /RTC1 /RTCc
SET(CMAKE_C_FLAGS_DEBUG "/Od /DEBUG /MTd")
SET(CMAKE_C_FLAGS_DEBUG "/Od /DEBUG /MTd /RTC1 /RTCs /RTCu")
SET(CMAKE_C_FLAGS_RELEASE "/MT /O2")
SET(WIN_RC "src/win32/git2.rc")
# Precompiled headers
ELSE ()
SET(CMAKE_C_FLAGS "-O2 -g -D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes -Wmissing-prototypes ${CMAKE_C_FLAGS}")
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
......@@ -127,29 +127,10 @@ INSTALL(DIRECTORY include/git2 DESTINATION ${INSTALL_INC} )
INSTALL(FILES include/git2.h DESTINATION ${INSTALL_INC} )
# Tests
IF (BUILD_TESTS)
SET(TEST_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.")
ADD_DEFINITIONS(-DTEST_RESOURCES=\"${TEST_RESOURCES}\")
INCLUDE_DIRECTORIES(tests)
FILE(GLOB SRC_TEST tests/t??-*.c)
ADD_EXECUTABLE(libgit2_test tests/test_main.c tests/test_lib.c tests/test_helpers.c ${SRC} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX})
TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT})
IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_test ws2_32)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
TARGET_LINK_LIBRARIES(libgit2_test socket nsl)
ENDIF ()
ENABLE_TESTING()
ADD_TEST(libgit2_test libgit2_test)
ENDIF ()
IF (BUILD_CLAR)
FIND_PACKAGE(PythonInterp REQUIRED)
SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources/")
SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar/resources/")
SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar")
ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
......
......@@ -70,7 +70,7 @@ The following CMake variables are declared:
- `INSTALL_LIB`: Where to install libraries to.
- `INSTALL_INC`: Where to install headers to.
- `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to ON)
- `BUILD_TESTS`: Build the libgit2 test suite (defaults to ON)
- `BUILD_CLAR`: Build [Clar](https://github.com/tanoku/clar)-based test suite (defaults to ON)
- `THREADSAFE`: Build libgit2 with threading support (defaults to OFF)
Language Bindings
......
......@@ -8,7 +8,7 @@ void test_buf_basic__resize(void)
git_buf buf1 = GIT_BUF_INIT;
git_buf_puts(&buf1, test_string);
cl_assert(git_buf_oom(&buf1) == 0);
cl_assert(strcmp(git_buf_cstr(&buf1), test_string) == 0);
cl_assert_strequal(git_buf_cstr(&buf1), test_string);
git_buf_puts(&buf1, test_string);
cl_assert(strlen(git_buf_cstr(&buf1)) == strlen(test_string) * 2);
......@@ -20,10 +20,10 @@ void test_buf_basic__printf(void)
git_buf buf2 = GIT_BUF_INIT;
git_buf_printf(&buf2, "%s %s %d ", "shoop", "da", 23);
cl_assert(git_buf_oom(&buf2) == 0);
cl_assert(strcmp(git_buf_cstr(&buf2), "shoop da 23 ") == 0);
cl_assert_strequal(git_buf_cstr(&buf2), "shoop da 23 ");
git_buf_printf(&buf2, "%s %d", "woop", 42);
cl_assert(git_buf_oom(&buf2) == 0);
cl_assert(strcmp(git_buf_cstr(&buf2), "shoop da 23 woop 42") == 0);
cl_assert_strequal(git_buf_cstr(&buf2), "shoop da 23 woop 42");
git_buf_free(&buf2);
}
......@@ -21,7 +21,7 @@ static int mv_read_cb(const char *name, const char *value, void *data)
if (!strcmp(name, _name))
(*n)++;
return 0;
return GIT_SUCCESS;
}
void test_config_multivar__foreach(void)
......
......@@ -26,9 +26,9 @@ void test_config_new__write_new_config(void)
cl_git_pass(git_config_add_file(config, file, 0));
cl_git_pass(git_config_get_string(config, "color.ui", &out));
cl_assert(strcmp(out, "auto") == 0);
cl_assert_strequal(out, "auto");
cl_git_pass(git_config_get_string(config, "core.editor", &out));
cl_assert(strcmp(out, "ed") == 0);
cl_assert_strequal(out, "ed");
git_config_free(config);
......
......@@ -28,9 +28,9 @@ void test_config_read__case_sensitive(void)
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1")));
cl_git_pass(git_config_get_string(cfg, "this.that.other", &str));
cl_assert(!strcmp(str, "true"));
cl_assert_strequal(str, "true");
cl_git_pass(git_config_get_string(cfg, "this.That.other", &str));
cl_assert(!strcmp(str, "yes"));
cl_assert_strequal(str, "yes");
cl_git_pass(git_config_get_bool(cfg, "this.that.other", &i));
cl_assert(i == 1);
......@@ -55,7 +55,7 @@ void test_config_read__multiline_value(void)
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2")));
cl_git_pass(git_config_get_string(cfg, "this.That.and", &str));
cl_assert(!strcmp(str, "one one one two two three three"));
cl_assert_strequal(str, "one one one two two three three");
git_config_free(cfg);
}
......@@ -71,7 +71,7 @@ void test_config_read__subsection_header(void)
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3")));
cl_git_pass(git_config_get_string(cfg, "section.subsection.var", &str));
cl_assert(!strcmp(str, "hello"));
cl_assert_strequal(str, "hello");
/* The subsection is transformed to lower-case */
cl_must_fail(git_config_get_string(cfg, "section.subSectIon.var", &str));
......@@ -171,10 +171,10 @@ void test_config_read__prefixes(void)
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
cl_git_pass(git_config_get_string(cfg, "remote.ab.url", &str));
cl_assert(strcmp(str, "http://example.com/git/ab") == 0);
cl_assert_strequal(str, "http://example.com/git/ab");
cl_git_pass(git_config_get_string(cfg, "remote.abba.url", &str));
cl_assert(strcmp(str, "http://example.com/git/abba") == 0);
cl_assert_strequal(str, "http://example.com/git/abba");
git_config_free(cfg);
}
......
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "clar_libgit2.h"
#include "hashtable.h"
#include "hash.h"
// Helpers
typedef struct _aux_object {
int __bulk;
git_oid id;
int visited;
int __bulk;
git_oid id;
int visited;
} table_item;
static uint32_t hash_func(const void *key, int hash_id)
{
uint32_t r;
const git_oid *id = key;
uint32_t r;
const git_oid *id = (const git_oid *)key;
memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r));
return r;
memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r));
return r;
}
static int hash_cmpkey(const void *a, const void *b)
{
return git_oid_cmp(a, b);
return git_oid_cmp((const git_oid*)a, (const git_oid*)b);
}
BEGIN_TEST(table0, "create a new hashtable")
git_hashtable *table = NULL;
table = git_hashtable_alloc(55, hash_func, hash_cmpkey);
must_be_true(table != NULL);
must_be_true(table->size_mask + 1 == 64);
git_hashtable_free(table);
END_TEST
BEGIN_TEST(table1, "fill the hashtable with random entries")
const int objects_n = 32;
int i;
table_item *objects;
git_hashtable *table = NULL;
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
must_be_true(table != NULL);
objects = git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
/* populate the hash table */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
/* make sure all the inserted objects can be found */
for (i = 0; i < objects_n; ++i) {
git_oid id;
table_item *ob;
git_hash_buf(&id, &i, sizeof(int));
ob = (table_item *)git_hashtable_lookup(table, &id);
must_be_true(ob != NULL);
must_be_true(ob == &(objects[i]));
}
/* make sure we cannot find inexisting objects */
for (i = 0; i < 50; ++i) {
int hash_id;
git_oid id;
hash_id = (rand() % 50000) + objects_n;
git_hash_buf(&id, &hash_id, sizeof(int));
must_be_true(git_hashtable_lookup(table, &id) == NULL);
}
git_hashtable_free(table);
git__free(objects);
END_TEST
void test_hash_table__new(void)
{
// create a new hashtable
git_hashtable *table = NULL;
BEGIN_TEST(table2, "make sure the table resizes automatically")
table = git_hashtable_alloc(55, hash_func, hash_cmpkey);
cl_assert(table != NULL);
cl_assert(table->size_mask + 1 == 64);
const int objects_n = 64;
int i;
unsigned int old_size;
table_item *objects;
git_hashtable *table = NULL;
git_hashtable_free(table);
}
table = git_hashtable_alloc(objects_n, hash_func, hash_cmpkey);
must_be_true(table != NULL);
void test_hash_table__fill(void)
{
// fill the hashtable with random entries
const int objects_n = 32;
int i;
table_item *objects;
git_hashtable *table = NULL;
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
cl_assert(table != NULL);
objects = (table_item *)git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
/* populate the hash table */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
cl_git_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
/* make sure all the inserted objects can be found */
for (i = 0; i < objects_n; ++i) {
git_oid id;
table_item *ob;
git_hash_buf(&id, &i, sizeof(int));
ob = (table_item *)git_hashtable_lookup(table, &id);
cl_assert(ob != NULL);
cl_assert(ob == &(objects[i]));
}
/* make sure we cannot find inexisting objects */
for (i = 0; i < 50; ++i) {
int hash_id;
git_oid id;
hash_id = (rand() % 50000) + objects_n;
git_hash_buf(&id, &hash_id, sizeof(int));
cl_assert(git_hashtable_lookup(table, &id) == NULL);
}
git_hashtable_free(table);
git__free(objects);
}
objects = git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
old_size = table->size_mask + 1;
void test_hash_table__resize(void)
{
// make sure the table resizes automatically
const int objects_n = 64;
int i;
unsigned int old_size;
table_item *objects;
git_hashtable *table = NULL;
/* populate the hash table -- should be automatically resized */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
table = git_hashtable_alloc(objects_n, hash_func, hash_cmpkey);
cl_assert(table != NULL);
must_be_true(table->size_mask > old_size);
objects = (table_item*)git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
/* make sure all the inserted objects can be found */
for (i = 0; i < objects_n; ++i) {
git_oid id;
table_item *ob;
old_size = table->size_mask + 1;
git_hash_buf(&id, &i, sizeof(int));
ob = (table_item *)git_hashtable_lookup(table, &id);
/* populate the hash table -- should be automatically resized */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
cl_git_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
must_be_true(ob != NULL);
must_be_true(ob == &(objects[i]));
}
cl_assert(table->size_mask > old_size);
git_hashtable_free(table);
git__free(objects);
/* make sure all the inserted objects can be found */
for (i = 0; i < objects_n; ++i) {
git_oid id;
table_item *ob;
END_TEST
git_hash_buf(&id, &i, sizeof(int));
ob = (table_item *)git_hashtable_lookup(table, &id);
BEGIN_TEST(tableit0, "iterate through all the contents of the table")
cl_assert(ob != NULL);
cl_assert(ob == &(objects[i]));
}
const int objects_n = 32;
int i;
table_item *objects, *ob;
git_hashtable_free(table);
git__free(objects);
}
git_hashtable *table = NULL;
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
must_be_true(table != NULL);
void test_hash_table__iterate(void)
{
// iterate through all the contents of the table
objects = git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
const int objects_n = 32;
int i;
table_item *objects, *ob;
/* populate the hash table */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
git_hashtable *table = NULL;
GIT_HASHTABLE_FOREACH_VALUE(table, ob, ob->visited = 1);
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
cl_assert(table != NULL);
/* make sure all nodes have been visited */
for (i = 0; i < objects_n; ++i)
must_be_true(objects[i].visited);
objects = git__malloc(objects_n * sizeof(table_item));
memset(objects, 0x0, objects_n * sizeof(table_item));
git_hashtable_free(table);
git__free(objects);
END_TEST
/* populate the hash table */
for (i = 0; i < objects_n; ++i) {
git_hash_buf(&(objects[i].id), &i, sizeof(int));
cl_git_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
}
GIT_HASHTABLE_FOREACH_VALUE(table, ob, ob->visited = 1);
BEGIN_SUITE(hashtable)
ADD_TEST(table0);
ADD_TEST(table1);
ADD_TEST(table2);
ADD_TEST(tableit0);
END_SUITE
/* make sure all nodes have been visited */
for (i = 0; i < objects_n; ++i)
{
cl_assert(objects[i].visited);
}
git_hashtable_free(table);
git__free(objects);
}
#include "clar_libgit2.h"
#include "index.h"
static const int index_entry_count = 109;
static const int index_entry_count_2 = 1437;
#define TEST_INDEX_PATH cl_fixture("testrepo.git/index")
#define TEST_INDEX2_PATH cl_fixture("gitgit.index")
#define TEST_INDEXBIG_PATH cl_fixture("big.index")
// Suite data
struct test_entry {
int index;
char path[128];
git_off_t file_size;
git_time_t mtime;
};
static struct test_entry test_entries[] = {
{4, "Makefile", 5064, 0x4C3F7F33},
{62, "tests/Makefile", 2631, 0x4C3F7F33},
{36, "src/index.c", 10014, 0x4C43368D},
{6, "git.git-authors", 2709, 0x4C3F7F33},
{48, "src/revobject.h", 1448, 0x4C3F7FE2}
};
// Helpers
static void copy_file(const char *src, const char *dst)
{
git_buf source_buf = GIT_BUF_INIT;
git_file dst_fd;
int error = GIT_ERROR;
cl_git_pass(git_futils_readbuffer(&source_buf, src));
dst_fd = git_futils_creat_withpath(dst, 0777, 0666);
if (dst_fd < 0)
goto cleanup;
cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size));
cleanup:
git_buf_free(&source_buf);
p_close(dst_fd);
}
static void files_are_equal(const char *a, const char *b)
{
git_buf buf_a = GIT_BUF_INIT;
git_buf buf_b = GIT_BUF_INIT;
int pass;
if (git_futils_readbuffer(&buf_a, a) < GIT_SUCCESS)
cl_assert(0);
if (git_futils_readbuffer(&buf_b, b) < GIT_SUCCESS) {
git_buf_free(&buf_a);
cl_assert(0);
}
pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size));
git_buf_free(&buf_a);
git_buf_free(&buf_b);
}
// Fixture setup and teardown
void test_index_tests__initialize(void)
{
}
void test_index_tests__cleanup(void)
{
}
void test_index_tests__empty_index(void)
{
git_index *index;
cl_git_pass(git_index_open(&index, "in-memory-index"));
cl_assert(index->on_disk == 0);
cl_assert(git_index_entrycount(index) == 0);
cl_assert(index->entries.sorted);
git_index_free(index);
}
void test_index_tests__default_test_index(void)
{
git_index *index;
unsigned int i;
git_index_entry **entries;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_assert(index->on_disk);
cl_assert(git_index_entrycount(index) == (unsigned int)index_entry_count);
cl_assert(index->entries.sorted);
entries = (git_index_entry **)index->entries.contents;
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
git_index_entry *e = entries[test_entries[i].index];
cl_assert_strequal(e->path, test_entries[i].path);
cl_assert(e->mtime.seconds == test_entries[i].mtime);
cl_assert(e->file_size == test_entries[i].file_size);
}
git_index_free(index);
}
void test_index_tests__gitgit_index(void)
{
git_index *index;
cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH));
cl_assert(index->on_disk);
cl_assert(git_index_entrycount(index) == (unsigned int)index_entry_count_2);
cl_assert(index->entries.sorted);
cl_assert(index->tree != NULL);
git_index_free(index);
}
void test_index_tests__find_in_existing(void)
{
git_index *index;
unsigned int i;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
int idx = git_index_find(index, test_entries[i].path);
cl_assert(idx == test_entries[i].index);
}
git_index_free(index);
}
void test_index_tests__find_in_empty(void)
{
git_index *index;
unsigned int i;
cl_git_pass(git_index_open(&index, "fake-index"));
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
int idx = git_index_find(index, test_entries[i].path);
cl_assert(idx == GIT_ENOTFOUND);
}
git_index_free(index);
}
void test_index_tests__write(void)
{
git_index *index;
copy_file(TEST_INDEXBIG_PATH, "index_rewrite");
cl_git_pass(git_index_open(&index, "index_rewrite"));
cl_assert(index->on_disk);
cl_git_pass(git_index_write(index));
files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite");
git_index_free(index);
p_unlink("index_rewrite");
}
void test_index_tests__sort0(void)
{
// sort the entires in an index
/*
* TODO: This no longer applies:
* index sorting in Git uses some specific changes to the way
* directories are sorted.
*
* We need to specificially check for this by creating a new
* index, adding entries in random order and then
* checking for consistency
*/
}
void test_index_tests__sort1(void)
{
// sort the entires in an empty index
git_index *index;
cl_git_pass(git_index_open(&index, "fake-index"));
/* FIXME: this test is slightly dumb */
cl_assert(index->entries.sorted);
git_index_free(index);
}
void test_index_tests__add(void)
{
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
git_repository *repo;
git_index_entry *entry;
git_oid id1;
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
/* Ensure we're the only guy in the room */
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
/* Create a new file in the working directory */
cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0));
cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
cl_git_pass(git_filebuf_commit(&file, 0666));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ echo "hey there" | git hash-object --stdin
*/
cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
/* Add the new file to the index */
cl_git_pass(git_index_add(index, "test.txt", 0));
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
entry = git_index_get(index, 0);
/* And the built-in hashing mechanism worked as expected */
cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
git_index_free(index);
git_repository_free(repo);
}
......@@ -28,6 +28,6 @@ void test_network_createremotethenload__cleanup(void)
void test_network_createremotethenload__parsing(void)
{
cl_assert(!strcmp(git_remote_name(_remote), "origin"));
cl_assert(!strcmp(git_remote_url(_remote), url));
cl_assert_strequal(git_remote_name(_remote), "origin");
cl_assert_strequal(git_remote_url(_remote), url);
}
......@@ -27,8 +27,8 @@ void test_network_remotes__cleanup(void)
void test_network_remotes__parsing(void)
{
cl_assert(!strcmp(git_remote_name(_remote), "test"));
cl_assert(!strcmp(git_remote_url(_remote), "git://github.com/libgit2/libgit2"));
cl_assert_strequal(git_remote_name(_remote), "test");
cl_assert_strequal(git_remote_url(_remote), "git://github.com/libgit2/libgit2");
}
void test_network_remotes__parsing_ssh_remote(void)
......@@ -53,24 +53,24 @@ void test_network_remotes__unsupported_transport_methods_are_unsupported(void)
void test_network_remotes__refspec_parsing(void)
{
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));
cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/remotes/test/*"));
cl_assert_strequal(git_refspec_src(_refspec), "refs/heads/*");
cl_assert_strequal(git_refspec_dst(_refspec), "refs/remotes/test/*");
}
void test_network_remotes__set_fetchspec(void)
{
cl_git_pass(git_remote_set_fetchspec(_remote, "refs/*:refs/*"));
_refspec = git_remote_fetchspec(_remote);
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/*"));
cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/*"));
cl_assert_strequal(git_refspec_src(_refspec), "refs/*");
cl_assert_strequal(git_refspec_dst(_refspec), "refs/*");
}
void test_network_remotes__set_pushspec(void)
{
cl_git_pass(git_remote_set_pushspec(_remote, "refs/*:refs/*"));
_refspec = git_remote_pushspec(_remote);
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/*"));
cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/*"));
cl_assert_strequal(git_refspec_src(_refspec), "refs/*");
cl_assert_strequal(git_refspec_dst(_refspec), "refs/*");
}
void test_network_remotes__save(void)
......@@ -90,13 +90,13 @@ void test_network_remotes__save(void)
_refspec = git_remote_fetchspec(_remote);
cl_assert(_refspec != NULL);
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));
cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/remotes/upstream/*"));
cl_assert_strequal(git_refspec_src(_refspec), "refs/heads/*");
cl_assert_strequal(git_refspec_dst(_refspec), "refs/remotes/upstream/*");
_refspec = git_remote_pushspec(_remote);
cl_assert(_refspec != NULL);
cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));
cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/heads/*"));
cl_assert_strequal(git_refspec_src(_refspec), "refs/heads/*");
cl_assert_strequal(git_refspec_dst(_refspec), "refs/heads/*");
}
void test_network_remotes__fnmatch(void)
......@@ -111,7 +111,7 @@ void test_network_remotes__transform(void)
memset(ref, 0x0, sizeof(ref));
cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master"));
cl_assert(!strcmp(ref, "refs/remotes/test/master"));
cl_assert_strequal(ref, "refs/remotes/test/master");
}
void test_network_remotes__transform_r(void)
......@@ -119,7 +119,7 @@ void test_network_remotes__transform_r(void)
git_buf buf = GIT_BUF_INIT;
cl_git_pass(git_refspec_transform_r(&buf, _refspec, "refs/heads/master"));
cl_assert(!strcmp(git_buf_cstr(&buf), "refs/remotes/test/master"));
cl_assert_strequal(git_buf_cstr(&buf), "refs/remotes/test/master");
git_buf_free(&buf);
}
......
......@@ -33,11 +33,11 @@ void test_notes_notes__1(void)
cl_git_pass(git_note_read(&_note, _repo, NULL, &oid));
cl_assert(!strcmp(git_note_message(_note), "hello world\n"));
cl_assert_strequal(git_note_message(_note), "hello world\n");
cl_assert(!git_oid_cmp(git_note_oid(_note), &note_oid));
cl_git_pass(git_blob_lookup(&_blob, _repo, &note_oid));
cl_assert(!strcmp(git_note_message(_note), git_blob_rawcontent(_blob)));
cl_assert_strequal(git_note_message(_note), git_blob_rawcontent(_blob));
cl_git_fail(git_note_create(&note_oid, _repo, _sig, _sig, NULL, &oid, "hello world\n"));
cl_git_fail(git_note_create(&note_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &oid, "hello world\n"));
......
......@@ -87,7 +87,7 @@ void test_object_raw_compare__compare_fmt_oids(void)
/* Format produced the right result */
out[GIT_OID_HEXSZ] = '\0';
cl_assert(strcmp(exp, out) == 0);
cl_assert_strequal(exp, out);
}
void test_object_raw_compare__compare_allocfmt_oids(void)
......@@ -100,7 +100,7 @@ void test_object_raw_compare__compare_allocfmt_oids(void)
out = git_oid_allocfmt(&in);
cl_assert(out);
cl_assert(strcmp(exp, out) == 0);
cl_assert_strequal(exp, out);
git__free(out);
}
......@@ -120,5 +120,5 @@ void test_object_raw_compare__compare_pathfmt_oids(void)
/* Format produced the right result */
out[GIT_OID_HEXSZ + 1] = '\0';
cl_assert(strcmp(exp2, out) == 0);
cl_assert_strequal(exp2, out);
}
......@@ -45,7 +45,7 @@ void test_object_raw_convert__succeed_on_oid_to_string_conversion(void)
/* returns out as hex formatted c-string */
str = git_oid_tostr(out, sizeof(out), &in);
cl_assert(str && str == out && *(str+GIT_OID_HEXSZ) == '\0');
cl_assert(strcmp(exp, out) == 0);
cl_assert_strequal(exp, out);
}
void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void)
......@@ -66,7 +66,7 @@ void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void)
/* returns big as hex formatted c-string */
str = git_oid_tostr(big, sizeof(big), &in);
cl_assert(str && str == big && *(str+GIT_OID_HEXSZ) == '\0');
cl_assert(strcmp(exp, big) == 0);
cl_assert_strequal(exp, big);
/* check tail material is untouched */
cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+1) == 'X');
......
......@@ -6,9 +6,13 @@
#include "data.h"
static int hash_object(git_oid *oid, git_rawobj *obj)
static void hash_object_pass(git_oid *oid, git_rawobj *obj)
{
return git_odb_hash(oid, obj->data, obj->len, obj->type);
cl_git_pass(git_odb_hash(oid, obj->data, obj->len, obj->type));
}
static void hash_object_fail(git_oid *oid, git_rawobj *obj)
{
cl_git_fail(git_odb_hash(oid, obj->data, obj->len, obj->type));
}
static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511";
......@@ -74,28 +78,28 @@ void test_object_raw_hash__hash_junk_data(void)
/* invalid types: */
junk_obj.data = some_data;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
junk_obj.type = GIT_OBJ__EXT1;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
junk_obj.type = GIT_OBJ__EXT2;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
junk_obj.type = GIT_OBJ_OFS_DELTA;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
junk_obj.type = GIT_OBJ_REF_DELTA;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
/* data can be NULL only if len is zero: */
junk_obj.type = GIT_OBJ_BLOB;
junk_obj.data = NULL;
cl_git_pass(hash_object(&id, &junk_obj));
hash_object_pass(&id, &junk_obj);
cl_assert(git_oid_cmp(&id, &id_zero) == 0);
junk_obj.len = 1;
cl_git_fail(hash_object(&id, &junk_obj));
hash_object_fail(&id, &junk_obj);
}
void test_object_raw_hash__hash_commit_object(void)
......@@ -103,7 +107,7 @@ void test_object_raw_hash__hash_commit_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, commit_id));
cl_git_pass(hash_object(&id2, &commit_obj));
hash_object_pass(&id2, &commit_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -112,7 +116,7 @@ void test_object_raw_hash__hash_tree_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, tree_id));
cl_git_pass(hash_object(&id2, &tree_obj));
hash_object_pass(&id2, &tree_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -121,7 +125,7 @@ void test_object_raw_hash__hash_tag_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, tag_id));
cl_git_pass(hash_object(&id2, &tag_obj));
hash_object_pass(&id2, &tag_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -130,7 +134,7 @@ void test_object_raw_hash__hash_zero_length_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, zero_id));
cl_git_pass(hash_object(&id2, &zero_obj));
hash_object_pass(&id2, &zero_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -139,7 +143,7 @@ void test_object_raw_hash__hash_one_byte_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, one_id));
cl_git_pass(hash_object(&id2, &one_obj));
hash_object_pass(&id2, &one_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -148,7 +152,7 @@ void test_object_raw_hash__hash_two_byte_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, two_id));
cl_git_pass(hash_object(&id2, &two_obj));
hash_object_pass(&id2, &two_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -157,6 +161,6 @@ void test_object_raw_hash__hash_multi_byte_object(void)
git_oid id1, id2;
cl_git_pass(git_oid_fromstr(&id1, some_id));
cl_git_pass(hash_object(&id2, &some_obj));
hash_object_pass(&id2, &some_obj);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......@@ -6,19 +6,19 @@
void test_object_raw_type2string__convert_type_to_string(void)
{
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_BAD), ""));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ__EXT1), ""));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_COMMIT), "commit"));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_TREE), "tree"));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_BLOB), "blob"));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_TAG), "tag"));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ__EXT2), ""));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"));
cl_assert(!strcmp(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA"));
cl_assert(!strcmp(git_object_type2string(-2), ""));
cl_assert(!strcmp(git_object_type2string(8), ""));
cl_assert(!strcmp(git_object_type2string(1234), ""));
cl_assert_strequal(git_object_type2string(GIT_OBJ_BAD), "");
cl_assert_strequal(git_object_type2string(GIT_OBJ__EXT1), "");
cl_assert_strequal(git_object_type2string(GIT_OBJ_COMMIT), "commit");
cl_assert_strequal(git_object_type2string(GIT_OBJ_TREE), "tree");
cl_assert_strequal(git_object_type2string(GIT_OBJ_BLOB), "blob");
cl_assert_strequal(git_object_type2string(GIT_OBJ_TAG), "tag");
cl_assert_strequal(git_object_type2string(GIT_OBJ__EXT2), "");
cl_assert_strequal(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA");
cl_assert_strequal(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA");
cl_assert_strequal(git_object_type2string(-2), "");
cl_assert_strequal(git_object_type2string(8), "");
cl_assert_strequal(git_object_type2string(1234), "");
}
void test_object_raw_type2string__convert_string_to_type(void)
......
#include "clar_libgit2.h"
#include "fileops.h"
#include "odb.h"
typedef struct object_data {
char *id; /* object id (sha1) */
char *dir; /* object store (fan-out) directory name */
char *file; /* object store filename */
} object_data;
static object_data commit = {
"3d7f8a6af076c8c3f20071a8935cdbe8228594d1",
"test-objects/3d",
"test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1",
};
static unsigned char commit_data[] = {
0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x3e, 0x0a,
};
static git_rawobj commit_obj = {
commit_data,
sizeof(commit_data),
GIT_OBJ_COMMIT
};
static object_data tree = {
"dff2da90b254e1beb889d1f1f1288be1803782df",
"test-objects/df",
"test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df",
};
static unsigned char tree_data[] = {
0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
};
static git_rawobj tree_obj = {
tree_data,
sizeof(tree_data),
GIT_OBJ_TREE
};
static object_data tag = {
"09d373e1dfdc16b129ceec6dd649739911541e05",
"test-objects/09",
"test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05",
};
static unsigned char tag_data[] = {
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
0x2e, 0x30, 0x2e, 0x31, 0x0a,
};
static git_rawobj tag_obj = {
tag_data,
sizeof(tag_data),
GIT_OBJ_TAG
};
static object_data zero = {
"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
"test-objects/e6",
"test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391",
};
static unsigned char zero_data[] = {
0x00 /* dummy data */
};
static git_rawobj zero_obj = {
zero_data,
0,
GIT_OBJ_BLOB
};
static object_data one = {
"8b137891791fe96927ad78e64b0aad7bded08bdc",
"test-objects/8b",
"test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc",
};
static unsigned char one_data[] = {
0x0a,
};
static git_rawobj one_obj = {
one_data,
sizeof(one_data),
GIT_OBJ_BLOB
};
static object_data two = {
"78981922613b2afb6025042ff6bd878ac1994e85",
"test-objects/78",
"test-objects/78/981922613b2afb6025042ff6bd878ac1994e85",
};
static unsigned char two_data[] = {
0x61, 0x0a,
};
static git_rawobj two_obj = {
two_data,
sizeof(two_data),
GIT_OBJ_BLOB
};
static object_data some = {
"fd8430bc864cfcd5f10e5590f8a447e01b942bfe",
"test-objects/fd",
"test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe",
};
static unsigned char some_data[] = {
0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
0x0a,
};
static git_rawobj some_obj = {
some_data,
sizeof(some_data),
GIT_OBJ_BLOB
};
static const char *odb_dir = "test-objects";
void test_body(object_data *d, git_rawobj *o);
// Helpers
static void remove_object_files(object_data *d)
{
cl_git_pass(p_unlink(d->file));
cl_git_pass(p_rmdir(d->dir));
cl_assert(errno != ENOTEMPTY);
cl_git_pass(p_rmdir(odb_dir) < 0);
}
static void streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw)
{
git_odb_stream *stream;
int error;
cl_git_pass(git_odb_open_wstream(&stream, odb, raw->len, raw->type));
stream->write(stream, raw->data, raw->len);
error = stream->finalize_write(oid, stream);
stream->free(stream);
cl_git_pass(error);
}
static void check_object_files(object_data *d)
{
cl_git_pass(git_path_exists(d->dir));
cl_git_pass(git_path_exists(d->file));
}
static void cmp_objects(git_rawobj *o1, git_rawobj *o2)
{
cl_assert(o1->type == o2->type);
cl_assert(o1->len == o2->len);
if (o1->len > 0)
cl_assert(memcmp(o1->data, o2->data, o1->len) == 0);
}
static void make_odb_dir(void)
{
cl_git_pass(p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE));
}
// Standard test form
void test_body(object_data *d, git_rawobj *o)
{
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
make_odb_dir();
cl_git_pass(git_odb_open(&db, odb_dir));
cl_git_pass(git_oid_fromstr(&id1, d->id));
streaming_write(&id2, db, o);
cl_assert(git_oid_cmp(&id1, &id2) == 0);
check_object_files(d);
cl_git_pass(git_odb_read(&obj, db, &id1));
cmp_objects(&obj->raw, o);
git_odb_object_free(obj);
git_odb_free(db);
remove_object_files(d);
}
void test_object_raw_write__loose_object(void)
{
object_data commit = {
"3d7f8a6af076c8c3f20071a8935cdbe8228594d1",
"test-objects/3d",
"test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1",
};
unsigned char commit_data[] = {
0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x3e, 0x0a,
};
git_rawobj commit_obj = {
commit_data,
sizeof(commit_data),
GIT_OBJ_COMMIT
};
test_body(&commit, &commit_obj);
}
void test_object_raw_write__loose_tree(void)
{
static object_data tree = {
"dff2da90b254e1beb889d1f1f1288be1803782df",
"test-objects/df",
"test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df",
};
static unsigned char tree_data[] = {
0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
};
static git_rawobj tree_obj = {
tree_data,
sizeof(tree_data),
GIT_OBJ_TREE
};
test_body(&tree, &tree_obj);
}
void test_object_raw_write__loose_tag(void)
{
static object_data tag = {
"09d373e1dfdc16b129ceec6dd649739911541e05",
"test-objects/09",
"test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05",
};
static unsigned char tag_data[] = {
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
0x2e, 0x30, 0x2e, 0x31, 0x0a,
};
static git_rawobj tag_obj = {
tag_data,
sizeof(tag_data),
GIT_OBJ_TAG
};
test_body(&tag, &tag_obj);
}
void test_object_raw_write__zero_length(void)
{
static object_data zero = {
"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
"test-objects/e6",
"test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391",
};
static unsigned char zero_data[] = {
0x00 /* dummy data */
};
static git_rawobj zero_obj = {
zero_data,
0,
GIT_OBJ_BLOB
};
test_body(&zero, &zero_obj);
}
void test_object_raw_write__one_byte(void)
{
static object_data one = {
"8b137891791fe96927ad78e64b0aad7bded08bdc",
"test-objects/8b",
"test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc",
};
static unsigned char one_data[] = {
0x0a,
};
static git_rawobj one_obj = {
one_data,
sizeof(one_data),
GIT_OBJ_BLOB
};
test_body(&one, &one_obj);
}
void test_object_raw_write__two_byte(void)
{
static object_data two = {
"78981922613b2afb6025042ff6bd878ac1994e85",
"test-objects/78",
"test-objects/78/981922613b2afb6025042ff6bd878ac1994e85",
};
static unsigned char two_data[] = {
0x61, 0x0a,
};
static git_rawobj two_obj = {
two_data,
sizeof(two_data),
GIT_OBJ_BLOB
};
test_body(&two, &two_obj);
}
void test_object_raw_write__several_bytes(void)
{
static object_data some = {
"fd8430bc864cfcd5f10e5590f8a447e01b942bfe",
"test-objects/fd",
"test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe",
};
static unsigned char some_data[] = {
0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
0x0a,
};
static git_rawobj some_obj = {
some_data,
sizeof(some_data),
GIT_OBJ_BLOB
};
test_body(&some, &some_obj);
}
#include "clar_libgit2.h"
#include "tag.h"
static const char *tag1_id = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1";
static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980";
static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755";
static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
static git_repository *g_repo;
// Helpers
static void ensure_tag_pattern_match(git_repository *repo,
const char *pattern,
const size_t expected_matches)
{
git_strarray tag_list;
int error = GIT_SUCCESS;
if ((error = git_tag_list_match(&tag_list, pattern, repo)) < GIT_SUCCESS)
goto exit;
if (tag_list.count != expected_matches)
error = GIT_ERROR;
exit:
git_strarray_free(&tag_list);
cl_git_pass(error);
}
// Fixture setup and teardown
void test_object_tag_read__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_object_tag_read__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_object_tag_read__parse(void)
{
// read and parse a tag from the repository
git_tag *tag1, *tag2;
git_commit *commit;
git_oid id1, id2, id_commit;
git_oid_fromstr(&id1, tag1_id);
git_oid_fromstr(&id2, tag2_id);
git_oid_fromstr(&id_commit, tagged_commit);
cl_git_pass(git_tag_lookup(&tag1, g_repo, &id1));
cl_assert_strequal(git_tag_name(tag1), "test");
cl_assert(git_tag_type(tag1) == GIT_OBJ_TAG);
cl_git_pass(git_tag_target((git_object **)&tag2, tag1));
cl_assert(tag2 != NULL);
cl_assert(git_oid_cmp(&id2, git_tag_id(tag2)) == 0);
cl_git_pass(git_tag_target((git_object **)&commit, tag2));
cl_assert(commit != NULL);
cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
git_tag_free(tag1);
git_tag_free(tag2);
git_commit_free(commit);
}
void test_object_tag_read__list(void)
{
// list all tag names from the repository
git_strarray tag_list;
cl_git_pass(git_tag_list(&tag_list, g_repo));
cl_assert(tag_list.count == 3);
git_strarray_free(&tag_list);
}
void test_object_tag_read__list_pattern(void)
{
// list all tag names from the repository matching a specified pattern
ensure_tag_pattern_match(g_repo, "", 3);
ensure_tag_pattern_match(g_repo, "*", 3);
ensure_tag_pattern_match(g_repo, "t*", 1);
ensure_tag_pattern_match(g_repo, "*b", 2);
ensure_tag_pattern_match(g_repo, "e", 0);
ensure_tag_pattern_match(g_repo, "e90810b", 1);
ensure_tag_pattern_match(g_repo, "e90810[ab]", 1);
}
void test_object_tag_read__parse_without_tagger(void)
{
// read and parse a tag without a tagger field
git_repository *bad_tag_repo;
git_tag *bad_tag;
git_commit *commit;
git_oid id, id_commit;
// TODO: This is a little messy
cl_git_pass(git_repository_open(&bad_tag_repo, cl_fixture("bad_tag.git")));
git_oid_fromstr(&id, bad_tag_id);
git_oid_fromstr(&id_commit, badly_tagged_commit);
cl_git_pass(git_tag_lookup(&bad_tag, bad_tag_repo, &id));
cl_assert(bad_tag != NULL);
cl_assert_strequal(git_tag_name(bad_tag), "e90810b");
cl_assert(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0);
cl_assert(bad_tag->tagger == NULL);
cl_git_pass(git_tag_target((git_object **)&commit, bad_tag));
cl_assert(commit != NULL);
cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
git_tag_free(bad_tag);
git_commit_free(commit);
git_repository_free(bad_tag_repo);
}
#include "clar_libgit2.h"
static const char* tagger_name = "Vicent Marti";
static const char* tagger_email = "vicent@github.com";
static const char* tagger_message = "This is my tag.\n\nThere are many tags, but this one is mine\n";
static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980";
static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
static git_repository *g_repo;
// Helpers
#ifndef GIT_WIN32
#include "odb.h"
static void locate_loose_object(const char *repository_folder,
git_object *object,
char **out,
char **out_folder)
{
static const char *objects_folder = "objects/";
char *ptr, *full_path, *top_folder;
int path_length, objects_length;
assert(repository_folder && object);
objects_length = strlen(objects_folder);
path_length = strlen(repository_folder);
ptr = full_path = git__malloc(path_length + objects_length + GIT_OID_HEXSZ + 3);
strcpy(ptr, repository_folder);
strcpy(ptr + path_length, objects_folder);
ptr = top_folder = ptr + path_length + objects_length;
*ptr++ = '/';
git_oid_pathfmt(ptr, git_object_id(object));
ptr += GIT_OID_HEXSZ + 1;
*ptr = 0;
*out = full_path;
if (out_folder)
*out_folder = top_folder;
}
static void loose_object_mode(const char *repository_folder, git_object *object)
{
char *object_path;
struct stat st;
locate_loose_object(repository_folder, object, &object_path, NULL);
cl_git_pass(p_stat(object_path, &st));
free(object_path);
cl_assert((st.st_mode & 0777) == GIT_OBJECT_FILE_MODE);
}
#endif
// Fixture setup and teardown
void test_object_tag_write__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_object_tag_write__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_object_tag_write__basic(void)
{
// write a tag to the repository and read it again
git_tag *tag;
git_oid target_id, tag_id;
git_signature *tagger;
const git_signature *tagger1;
git_reference *ref_tag;
git_object *target;
git_oid_fromstr(&target_id, tagged_commit);
cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
cl_git_pass(git_tag_create(
&tag_id, /* out id */
g_repo,
"the-tag",
target,
tagger,
tagger_message,
0));
git_object_free(target);
git_signature_free(tagger);
cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id));
cl_assert(git_oid_cmp(git_tag_target_oid(tag), &target_id) == 0);
/* Check attributes were set correctly */
tagger1 = git_tag_tagger(tag);
cl_assert(tagger1 != NULL);
cl_assert_strequal(tagger1->name, tagger_name);
cl_assert_strequal(tagger1->email, tagger_email);
cl_assert(tagger1->when.time == 123456789);
cl_assert(tagger1->when.offset == 60);
cl_assert_strequal(git_tag_message(tag), tagger_message);
cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/the-tag"));
cl_assert(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
cl_git_pass(git_reference_delete(ref_tag));
#ifndef GIT_WIN32
// TODO: Get this to work on Linux
//loose_object_mode("testrepo/", (git_object *)tag);
#endif
git_tag_free(tag);
}
void test_object_tag_write__overwrite(void)
{
// Attempt to write a tag bearing the same name than an already existing tag
git_oid target_id, tag_id;
git_signature *tagger;
git_object *target;
git_oid_fromstr(&target_id, tagged_commit);
cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
cl_git_fail(git_tag_create(
&tag_id, /* out id */
g_repo,
"e90810b",
target,
tagger,
tagger_message,
0));
git_object_free(target);
git_signature_free(tagger);
}
void test_object_tag_write__replace(void)
{
// Replace an already existing tag
git_oid target_id, tag_id, old_tag_id;
git_signature *tagger;
git_reference *ref_tag;
git_object *target;
git_oid_fromstr(&target_id, tagged_commit);
cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b"));
git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
git_reference_free(ref_tag);
/* create signature */
cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
cl_git_pass(git_tag_create(
&tag_id, /* out id */
g_repo,
"e90810b",
target,
tagger,
tagger_message,
1));
git_object_free(target);
git_signature_free(tagger);
cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b"));
cl_assert(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
cl_assert(git_oid_cmp(git_reference_oid(ref_tag), &old_tag_id) != 0);
git_reference_free(ref_tag);
}
void test_object_tag_write__lightweight(void)
{
// write a lightweight tag to the repository and read it again
git_oid target_id, object_id;
git_reference *ref_tag;
git_object *target;
git_oid_fromstr(&target_id, tagged_commit);
cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
cl_git_pass(git_tag_create_lightweight(
&object_id,
g_repo,
"light-tag",
target,
0));
git_object_free(target);
cl_assert(git_oid_cmp(&object_id, &target_id) == 0);
cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/light-tag"));
cl_assert(git_oid_cmp(git_reference_oid(ref_tag), &target_id) == 0);
cl_git_pass(git_tag_delete(g_repo, "light-tag"));
git_reference_free(ref_tag);
}
void test_object_tag_write__lightweight_over_existing(void)
{
// Attempt to write a lightweight tag bearing the same name than an already existing tag
git_oid target_id, object_id, existing_object_id;
git_object *target;
git_oid_fromstr(&target_id, tagged_commit);
cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
cl_git_fail(git_tag_create_lightweight(
&object_id,
g_repo,
"e90810b",
target,
0));
git_oid_fromstr(&existing_object_id, tag2_id);
cl_assert(git_oid_cmp(&object_id, &existing_object_id) == 0);
git_object_free(target);
}
void test_object_tag_write__delete(void)
{
// Delete an already existing tag
git_reference *ref_tag;
cl_git_pass(git_tag_delete(g_repo, "e90810b"));
cl_git_fail(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b"));
git_reference_free(ref_tag);
}
......@@ -18,7 +18,7 @@ static void diff_cmp(const git_tree_diff_data *a, const git_tree_diff_data *b)
cl_assert(a->status - b->status == 0);
cl_assert(strcmp(a->path, b->path) == 0);
cl_assert_strequal(a->path, b->path);
}
static int diff_cb(const git_tree_diff_data *diff, void *data)
......
......@@ -24,7 +24,10 @@ void test_object_tree_frompath__cleanup(void)
cl_fixture_cleanup("testrepo.git");
}
static void assert_tree_from_path(git_tree *root, const char *path, git_error expected_result, const char *expected_raw_oid)
static void assert_tree_from_path(git_tree *root,
const char *path,
git_error expected_result,
const char *expected_raw_oid)
{
git_tree *containing_tree = NULL;
......@@ -35,7 +38,7 @@ static void assert_tree_from_path(git_tree *root, const char *path, git_error ex
cl_assert(containing_tree != NULL && expected_result == GIT_SUCCESS);
cl_assert(git_oid_streq(git_object_id((const git_object *)containing_tree), expected_raw_oid) == GIT_SUCCESS);
cl_git_pass(git_oid_streq(git_object_id((const git_object *)containing_tree), expected_raw_oid));
git_tree_free(containing_tree);
}
......
#include "clar_libgit2.h"
#include "tree.h"
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
static git_repository *g_repo;
// Fixture setup and teardown
void test_object_tree_read__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_object_tree_read__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_object_tree_read__loaded(void)
{
// acces randomly the entries on a loaded tree
git_oid id;
git_tree *tree;
git_oid_fromstr(&id, tree_oid);
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_assert(git_tree_entry_byname(tree, "README") != NULL);
cl_assert(git_tree_entry_byname(tree, "NOTEXISTS") == NULL);
cl_assert(git_tree_entry_byname(tree, "") == NULL);
cl_assert(git_tree_entry_byindex(tree, 0) != NULL);
cl_assert(git_tree_entry_byindex(tree, 2) != NULL);
cl_assert(git_tree_entry_byindex(tree, 3) == NULL);
cl_assert(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL);
git_tree_free(tree);
}
void test_object_tree_read__two(void)
{
// read a tree from the repository
git_oid id;
git_tree *tree;
const git_tree_entry *entry;
git_object *obj;
git_oid_fromstr(&id, tree_oid);
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_assert(git_tree_entrycount(tree) == 3);
/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
cl_assert(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_TREE) == 0);
cl_assert(obj != NULL);
git_object_free(obj);
obj = NULL;
cl_assert(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_BLOB) == GIT_EINVALIDTYPE);
cl_assert(obj == NULL);
entry = git_tree_entry_byname(tree, "README");
cl_assert(entry != NULL);
cl_assert_strequal(git_tree_entry_name(entry), "README");
cl_git_pass(git_tree_entry_2object(&obj, g_repo, entry));
cl_assert(obj != NULL);
git_object_free(obj);
git_tree_free(tree);
}
#include "clar_libgit2.h"
#include "tree.h"
static const char *blob_oid = "fa49b077972391ad58037050f2a75f74e3671e92";
static const char *first_tree = "181037049a54a1eb5fab404658a3a250b44335d7";
static const char *second_tree = "f60079018b664e4e79329a7ef9559c8d9e0378d1";
static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488";
static git_repository *g_repo;
// Helpers
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
{
static const char *indent = " ";
git_tree *tree;
unsigned int i;
if (git_tree_lookup(&tree, repo, tree_oid) < GIT_SUCCESS)
return GIT_ERROR;
for (i = 0; i < git_tree_entrycount(tree); ++i) {
const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
char entry_oid[40];
git_oid_fmt(entry_oid, &entry->oid);
printf("%.*s%o [%.*s] %s\n", depth*2, indent, entry->attr, 40, entry_oid, entry->filename);
if (entry->attr == S_IFDIR) {
if (print_tree(repo, &entry->oid, depth + 1) < GIT_SUCCESS) {
git_tree_free(tree);
return GIT_ERROR;
}
}
}
git_tree_free(tree);
return GIT_SUCCESS;
}
static void locate_loose_object(const char *repository_folder,
git_object *object,
char **out,
char **out_folder)
{
static const char *objects_folder = "objects/";
char *ptr, *full_path, *top_folder;
int path_length, objects_length;
assert(repository_folder && object);
objects_length = strlen(objects_folder);
path_length = strlen(repository_folder);
ptr = full_path = git__malloc(path_length + objects_length + GIT_OID_HEXSZ + 3);
strcpy(ptr, repository_folder);
strcpy(ptr + path_length, objects_folder);
ptr = top_folder = ptr + path_length + objects_length;
*ptr++ = '/';
git_oid_pathfmt(ptr, git_object_id(object));
ptr += GIT_OID_HEXSZ + 1;
*ptr = 0;
*out = full_path;
if (out_folder)
*out_folder = top_folder;
}
static int loose_object_mode(const char *repository_folder, git_object *object)
{
char *object_path;
struct stat st;
locate_loose_object(repository_folder, object, &object_path, NULL);
if (p_stat(object_path, &st) < 0)
return 0;
free(object_path);
return st.st_mode;
}
static int loose_object_dir_mode(const char *repository_folder, git_object *object)
{
char *object_path;
size_t pos;
struct stat st;
locate_loose_object(repository_folder, object, &object_path, NULL);
pos = strlen(object_path);
while (pos--) {
if (object_path[pos] == '/') {
object_path[pos] = 0;
break;
}
}
if (p_stat(object_path, &st) < 0)
return 0;
free(object_path);
return st.st_mode;
}
// Fixture setup and teardown
void test_object_tree_write__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_object_tree_write__cleanup(void)
{
cl_git_sandbox_cleanup();
}
#if 0
void xtest_object_tree_write__print(void)
{
// write a tree from an index
git_index *index;
git_oid tree_oid;
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_tree_create_fromindex(&tree_oid, index));
cl_git_pass(print_tree(g_repo, &tree_oid, 0));
}
#endif
void test_object_tree_write__from_memory(void)
{
// write a tree from a memory
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, rid, id2;
git_oid_fromstr(&id, first_tree);
git_oid_fromstr(&id2, second_tree);
git_oid_fromstr(&bid, blob_oid);
//create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER.
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_git_pass(git_treebuilder_create(&builder, tree));
cl_git_fail(git_treebuilder_insert(NULL, builder, "", &bid, 0100644));
cl_git_fail(git_treebuilder_insert(NULL, builder, "/", &bid, 0100644));
cl_git_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", &bid, 0100644));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
cl_git_pass(git_treebuilder_write(&rid, g_repo, builder));
cl_assert(git_oid_cmp(&rid, &id2) == 0);
git_treebuilder_free(builder);
git_tree_free(tree);
}
void test_object_tree_write__subtree(void)
{
// write a hierarchical tree from a memory
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, subtree_id, id2, id3;
git_oid id_hiearar;
git_oid_fromstr(&id, first_tree);
git_oid_fromstr(&id2, second_tree);
git_oid_fromstr(&id3, third_tree);
git_oid_fromstr(&bid, blob_oid);
//create subtree
cl_git_pass(git_treebuilder_create(&builder, NULL));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder));
git_treebuilder_free(builder);
// create parent tree
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_git_pass(git_treebuilder_create(&builder, tree));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000));
cl_git_pass(git_treebuilder_write(&id_hiearar, g_repo, builder));
git_treebuilder_free(builder);
git_tree_free(tree);
cl_assert(git_oid_cmp(&id_hiearar, &id3) == 0);
// check data is correct
cl_git_pass(git_tree_lookup(&tree, g_repo, &id_hiearar));
cl_assert(2 == git_tree_entrycount(tree));
#ifndef GIT_WIN32
// TODO: fix these
//cl_assert((loose_object_dir_mode("testrepo", (git_object *)tree) & 0777) == GIT_OBJECT_DIR_MODE);
//cl_assert((loose_object_mode("testrespo", (git_object *)tree) & 0777) == GIT_OBJECT_FILE_MODE);
#endif
git_tree_free(tree);
}
......@@ -11,7 +11,7 @@ void test_refs_crashes__double_free(void)
cl_git_pass(git_reference_lookup(&ref2, repo, REFNAME));
cl_git_pass(git_reference_delete(ref));
/* reference is gone from disk, so reloading it will fail */
cl_must_fail(git_reference_reload(ref2));
cl_git_fail(git_reference_reload(ref2));
git_repository_free(repo);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
static const char *current_head_target = "refs/heads/master";
static git_repository *g_repo;
void test_ref_create__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_ref_create__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_ref_create__symbolic(void)
{
// create a new symbolic reference
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo2;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "another-head-tracker";
git_oid_fromstr(&id, current_master_tip);
/* Retrieve the physical path to the symbolic ref for further cleaning */
cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head_tracker));
git_buf_free(&ref_path);
/* Create and write the new symbolic reference */
cl_git_pass(git_reference_create_symbolic(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
/* Ensure the reference can be looked-up... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
cl_assert(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC);
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
cl_assert_strequal(looked_up_ref->name, new_head_tracker);
/* ...peeled.. */
cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID);
/* ...and that it points to the current master tip */
cl_assert(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
/* Similar test with a fresh new repository */
cl_git_pass(git_repository_open(&repo2, "testrepo"));
cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker));
cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
cl_assert(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_repository_free(repo2);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
}
void test_ref_create__deep_symbolic(void)
{
// create a deep symbolic reference
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "deep/rooted/tracker";
git_oid_fromstr(&id, current_master_tip);
cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head_tracker));
cl_git_pass(git_reference_create_symbolic(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
cl_assert(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
git_buf_free(&ref_path);
}
void test_ref_create__oid(void)
{
// create a new OID reference
git_reference *new_reference, *looked_up_ref;
git_repository *repo2;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head = "refs/heads/new-head";
git_oid_fromstr(&id, current_master_tip);
/* Retrieve the physical path to the symbolic ref for further cleaning */
cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head));
/* Create and write the new object id reference */
cl_git_pass(git_reference_create_oid(&new_reference, g_repo, new_head, &id, 0));
/* Ensure the reference can be looked-up... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head));
cl_assert(git_reference_type(looked_up_ref) & GIT_REF_OID);
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
cl_assert_strequal(looked_up_ref->name, new_head);
/* ...and that it points to the current master tip */
cl_assert(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_reference_free(looked_up_ref);
/* Similar test with a fresh new repository */
cl_git_pass(git_repository_open(&repo2, "testrepo"));
cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head));
cl_assert(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_repository_free(repo2);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_buf_free(&ref_path);
}
void test_ref_create__oid_unknown(void)
{
// Can not create a new OID reference which targets at an unknown id
git_reference *new_reference, *looked_up_ref;
git_oid id;
const char *new_head = "refs/heads/new-head";
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
/* Create and write the new object id reference */
cl_git_fail(git_reference_create_oid(&new_reference, g_repo, new_head, &id, 0));
/* Ensure the reference can't be looked-up... */
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, new_head));
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *packed_test_head_name = "refs/heads/packed-test";
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
static git_repository *g_repo;
void test_refs_delete__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_refs_delete__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refs_delete__packed_loose(void)
{
// deleting a ref which is both packed and loose should remove both tracks in the filesystem
git_reference *looked_up_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
/* Ensure the loose reference exists on the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, packed_test_head_name));
cl_git_pass(git_path_exists(temp_path.ptr));
/* Lookup the reference */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
/* Ensure it's the loose version that has been found */
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is deleted... */
cl_git_pass(git_reference_delete(looked_up_ref));
/* Looking up the reference once again should not retrieve it */
cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
/* Ensure the loose reference doesn't exist any longer on the file system */
cl_git_pass(!git_path_exists(temp_path.ptr));
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_delete__packed_only(void)
{
// can delete a just packed reference
git_reference *ref;
git_oid id;
const char *new_ref = "refs/heads/new_ref";
git_oid_fromstr(&id, current_master_tip);
/* Create and write the new object id reference */
cl_git_pass(git_reference_create_oid(&ref, g_repo, new_ref, &id, 0));
git_reference_free(ref);
/* Lookup the reference */
cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref));
/* Ensure it's a loose reference */
cl_assert(git_reference_is_packed(ref) == 0);
/* Pack all existing references */
cl_git_pass(git_reference_packall(g_repo));
/* Reload the reference from disk */
cl_git_pass(git_reference_reload(ref));
/* Ensure it's a packed reference */
cl_assert(git_reference_is_packed(ref) == 1);
/* This should pass */
cl_git_pass(git_reference_delete(ref));
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static git_repository *g_repo;
void test_refs_list__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_refs_list__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refs_list__all(void)
{
// try to list all the references in our test repo
git_strarray ref_list;
cl_git_pass(git_reference_listall(&ref_list, g_repo, GIT_REF_LISTALL));
/*{
unsigned short i;
for (i = 0; i < ref_list.count; ++i)
printf("# %s\n", ref_list.strings[i]);
}*/
/* We have exactly 9 refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
cl_assert(ref_list.count == 9);
git_strarray_free(&ref_list);
}
void test_refs_list__symbolic_only(void)
{
// try to list only the symbolic references
git_strarray ref_list;
cl_git_pass(git_reference_listall(&ref_list, g_repo, GIT_REF_SYMBOLIC));
cl_assert(ref_list.count == 0); /* no symrefs in the test repo */
git_strarray_free(&ref_list);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
// Helpers
static void ensure_refname_normalized(int is_oid_ref,
const char *input_refname,
const char *expected_refname)
{
char buffer_out[GIT_REFNAME_MAX];
if (is_oid_ref)
cl_git_pass(git_reference__normalize_name_oid(buffer_out, sizeof(buffer_out), input_refname));
else
cl_git_pass(git_reference__normalize_name(buffer_out, sizeof(buffer_out), input_refname));
if (expected_refname)
cl_assert(0 == strcmp(buffer_out, expected_refname));
}
static void ensure_refname_invalid(int is_oid_ref, const char *input_refname)
{
char buffer_out[GIT_REFNAME_MAX];
if (is_oid_ref)
cl_git_fail(git_reference__normalize_name_oid(buffer_out, sizeof(buffer_out), input_refname));
else
cl_git_fail(git_reference__normalize_name(buffer_out, sizeof(buffer_out), input_refname));
}
#define OID_REF 1
#define SYM_REF 0
void test_refs_normalize__direct(void)
{
// normalize a direct (OID) reference name
ensure_refname_invalid(OID_REF, "a");
ensure_refname_invalid(OID_REF, "");
ensure_refname_invalid(OID_REF, "refs/heads/a/");
ensure_refname_invalid(OID_REF, "refs/heads/a.");
ensure_refname_invalid(OID_REF, "refs/heads/a.lock");
ensure_refname_normalized(OID_REF, "refs/dummy/a", NULL);
ensure_refname_normalized(OID_REF, "refs/stash", NULL);
ensure_refname_normalized(OID_REF, "refs/tags/a", "refs/tags/a");
ensure_refname_normalized(OID_REF, "refs/heads/a/b", "refs/heads/a/b");
ensure_refname_normalized(OID_REF, "refs/heads/a./b", "refs/heads/a./b");
ensure_refname_invalid(OID_REF, "refs/heads/foo?bar");
ensure_refname_invalid(OID_REF, "refs/heads\foo");
ensure_refname_normalized(OID_REF, "refs/heads/v@ation", "refs/heads/v@ation");
ensure_refname_normalized(OID_REF, "refs///heads///a", "refs/heads/a");
ensure_refname_invalid(OID_REF, "refs/heads/.a/b");
ensure_refname_invalid(OID_REF, "refs/heads/foo/../bar");
ensure_refname_invalid(OID_REF, "refs/heads/foo..bar");
ensure_refname_invalid(OID_REF, "refs/heads/./foo");
ensure_refname_invalid(OID_REF, "refs/heads/v@{ation");
}
void test_refs_normalize__symbolic(void)
{
// normalize a symbolic reference name
ensure_refname_normalized(SYM_REF, "a", "a");
ensure_refname_normalized(SYM_REF, "a/b", "a/b");
ensure_refname_normalized(SYM_REF, "refs///heads///a", "refs/heads/a");
ensure_refname_invalid(SYM_REF, "");
ensure_refname_invalid(SYM_REF, "heads\foo");
}
/* Ported from JGit, BSD licence.
* See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
void test_refs_normalize__jgit_suite(void)
{
// tests borrowed from JGit
/* EmptyString */
ensure_refname_invalid(SYM_REF, "");
ensure_refname_invalid(SYM_REF, "/");
/* MustHaveTwoComponents */
ensure_refname_invalid(OID_REF, "master");
ensure_refname_normalized(SYM_REF, "heads/master", "heads/master");
/* ValidHead */
ensure_refname_normalized(SYM_REF, "refs/heads/master", "refs/heads/master");
ensure_refname_normalized(SYM_REF, "refs/heads/pu", "refs/heads/pu");
ensure_refname_normalized(SYM_REF, "refs/heads/z", "refs/heads/z");
ensure_refname_normalized(SYM_REF, "refs/heads/FoO", "refs/heads/FoO");
/* ValidTag */
ensure_refname_normalized(SYM_REF, "refs/tags/v1.0", "refs/tags/v1.0");
/* NoLockSuffix */
ensure_refname_invalid(SYM_REF, "refs/heads/master.lock");
/* NoDirectorySuffix */
ensure_refname_invalid(SYM_REF, "refs/heads/master/");
/* NoSpace */
ensure_refname_invalid(SYM_REF, "refs/heads/i haz space");
/* NoAsciiControlCharacters */
{
char c;
char buffer[GIT_REFNAME_MAX];
for (c = '\1'; c < ' '; c++) {
strncpy(buffer, "refs/heads/mast", 15);
strncpy(buffer + 15, (const char *)&c, 1);
strncpy(buffer + 16, "er", 2);
buffer[18 - 1] = '\0';
ensure_refname_invalid(SYM_REF, buffer);
}
}
/* NoBareDot */
ensure_refname_invalid(SYM_REF, "refs/heads/.");
ensure_refname_invalid(SYM_REF, "refs/heads/..");
ensure_refname_invalid(SYM_REF, "refs/heads/./master");
ensure_refname_invalid(SYM_REF, "refs/heads/../master");
/* NoLeadingOrTrailingDot */
ensure_refname_invalid(SYM_REF, ".");
ensure_refname_invalid(SYM_REF, "refs/heads/.bar");
ensure_refname_invalid(SYM_REF, "refs/heads/..bar");
ensure_refname_invalid(SYM_REF, "refs/heads/bar.");
/* ContainsDot */
ensure_refname_normalized(SYM_REF, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r");
ensure_refname_invalid(SYM_REF, "refs/heads/master..pu");
/* NoMagicRefCharacters */
ensure_refname_invalid(SYM_REF, "refs/heads/master^");
ensure_refname_invalid(SYM_REF, "refs/heads/^master");
ensure_refname_invalid(SYM_REF, "^refs/heads/master");
ensure_refname_invalid(SYM_REF, "refs/heads/master~");
ensure_refname_invalid(SYM_REF, "refs/heads/~master");
ensure_refname_invalid(SYM_REF, "~refs/heads/master");
ensure_refname_invalid(SYM_REF, "refs/heads/master:");
ensure_refname_invalid(SYM_REF, "refs/heads/:master");
ensure_refname_invalid(SYM_REF, ":refs/heads/master");
/* ShellGlob */
ensure_refname_invalid(SYM_REF, "refs/heads/master?");
ensure_refname_invalid(SYM_REF, "refs/heads/?master");
ensure_refname_invalid(SYM_REF, "?refs/heads/master");
ensure_refname_invalid(SYM_REF, "refs/heads/master[");
ensure_refname_invalid(SYM_REF, "refs/heads/[master");
ensure_refname_invalid(SYM_REF, "[refs/heads/master");
ensure_refname_invalid(SYM_REF, "refs/heads/master*");
ensure_refname_invalid(SYM_REF, "refs/heads/*master");
ensure_refname_invalid(SYM_REF, "*refs/heads/master");
/* ValidSpecialCharacters */
ensure_refname_normalized(SYM_REF, "refs/heads/!", "refs/heads/!");
ensure_refname_normalized(SYM_REF, "refs/heads/\"", "refs/heads/\"");
ensure_refname_normalized(SYM_REF, "refs/heads/#", "refs/heads/#");
ensure_refname_normalized(SYM_REF, "refs/heads/$", "refs/heads/$");
ensure_refname_normalized(SYM_REF, "refs/heads/%", "refs/heads/%");
ensure_refname_normalized(SYM_REF, "refs/heads/&", "refs/heads/&");
ensure_refname_normalized(SYM_REF, "refs/heads/'", "refs/heads/'");
ensure_refname_normalized(SYM_REF, "refs/heads/(", "refs/heads/(");
ensure_refname_normalized(SYM_REF, "refs/heads/)", "refs/heads/)");
ensure_refname_normalized(SYM_REF, "refs/heads/+", "refs/heads/+");
ensure_refname_normalized(SYM_REF, "refs/heads/,", "refs/heads/,");
ensure_refname_normalized(SYM_REF, "refs/heads/-", "refs/heads/-");
ensure_refname_normalized(SYM_REF, "refs/heads/;", "refs/heads/;");
ensure_refname_normalized(SYM_REF, "refs/heads/<", "refs/heads/<");
ensure_refname_normalized(SYM_REF, "refs/heads/=", "refs/heads/=");
ensure_refname_normalized(SYM_REF, "refs/heads/>", "refs/heads/>");
ensure_refname_normalized(SYM_REF, "refs/heads/@", "refs/heads/@");
ensure_refname_normalized(SYM_REF, "refs/heads/]", "refs/heads/]");
ensure_refname_normalized(SYM_REF, "refs/heads/_", "refs/heads/_");
ensure_refname_normalized(SYM_REF, "refs/heads/`", "refs/heads/`");
ensure_refname_normalized(SYM_REF, "refs/heads/{", "refs/heads/{");
ensure_refname_normalized(SYM_REF, "refs/heads/|", "refs/heads/|");
ensure_refname_normalized(SYM_REF, "refs/heads/}", "refs/heads/}");
// This is valid on UNIX, but not on Windows
// hence we make in invalid due to non-portability
//
ensure_refname_invalid(SYM_REF, "refs/heads/\\");
/* UnicodeNames */
/*
* Currently this fails.
* ensure_refname_normalized(SYM_REF, "refs/heads/\u00e5ngstr\u00f6m", "refs/heads/\u00e5ngstr\u00f6m");
*/
/* RefLogQueryIsValidRef */
ensure_refname_invalid(SYM_REF, "refs/heads/master@{1}");
ensure_refname_invalid(SYM_REF, "refs/heads/master@{1.hour.ago}");
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *ref_name = "refs/heads/other";
static const char *ref_master_name = "refs/heads/master";
static const char *ref_branch_name = "refs/heads/branch";
static const char *ref_test_name = "refs/heads/test";
static git_repository *g_repo;
void test_ref_overwrite__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_ref_overwrite__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_ref_overwrite__symbolic(void)
{
// Overwrite an existing symbolic reference
git_reference *ref, *branch_ref;
/* The target needds to exist and we need to check the name has changed */
cl_git_pass(git_reference_create_symbolic(&branch_ref, g_repo, ref_branch_name, ref_master_name, 0));
cl_git_pass(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_branch_name, 0));
git_reference_free(ref);
/* Ensure it points to the right place*/
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name));
cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC);
cl_assert_strequal(git_reference_target(ref), ref_branch_name);
git_reference_free(ref);
/* Ensure we can't create it unless we force it to */
cl_git_fail(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_master_name, 0));
cl_git_pass(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_master_name, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name));
cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC);
cl_assert_strequal(git_reference_target(ref), ref_master_name);
git_reference_free(ref);
git_reference_free(branch_ref);
}
void test_ref_overwrite__object_id(void)
{
// Overwrite an existing object id reference
git_reference *ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Create it */
cl_git_pass(git_reference_create_oid(&ref, g_repo, ref_name, &id, 0));
git_reference_free(ref);
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_test_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Ensure we can't overwrite unless we force it */
cl_git_fail(git_reference_create_oid(&ref, g_repo, ref_name, &id, 0));
cl_git_pass(git_reference_create_oid(&ref, g_repo, ref_name, &id, 1));
git_reference_free(ref);
/* Ensure it has been overwritten */
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name));
cl_assert(!git_oid_cmp(&id, git_reference_oid(ref)));
git_reference_free(ref);
}
void test_ref_overwrite__object_id_with_symbolic(void)
{
// Overwrite an existing object id reference with a symbolic one
git_reference *ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
cl_git_pass(git_reference_create_oid(&ref, g_repo, ref_name, &id, 0));
git_reference_free(ref);
cl_git_fail(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_master_name, 0));
cl_git_pass(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_master_name, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name));
cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC);
cl_assert_strequal(git_reference_target(ref), ref_master_name);
git_reference_free(ref);
}
void test_ref_overwrite__symbolic_with_object_id(void)
{
// Overwrite an existing symbolic reference with an object id one
git_reference *ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Create the symbolic ref */
cl_git_pass(git_reference_create_symbolic(&ref, g_repo, ref_name, ref_master_name, 0));
git_reference_free(ref);
/* It shouldn't overwrite unless we tell it to */
cl_git_fail(git_reference_create_oid(&ref, g_repo, ref_name, &id, 0));
cl_git_pass(git_reference_create_oid(&ref, g_repo, ref_name, &id, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
cl_assert(!git_oid_cmp(git_reference_oid(ref), &id));
git_reference_free(ref);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *loose_tag_ref_name = "refs/tags/e90810b";
static git_repository *g_repo;
void test_ref_pack__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_ref_pack__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_ref_pack__empty(void)
{
// create a packfile for an empty folder
git_buf temp_path = GIT_BUF_INIT;
cl_git_pass(git_buf_join_n(&temp_path, '/', 3, g_repo->path_repository, GIT_REFS_HEADS_DIR, "empty_dir"));
cl_git_pass(git_futils_mkdir_r(temp_path.ptr, NULL, GIT_REFS_DIR_MODE));
git_buf_free(&temp_path);
cl_git_pass(git_reference_packall(g_repo));
}
void test_ref_pack__loose(void)
{
// create a packfile from all the loose rn a repo
git_reference *reference;
git_buf temp_path = GIT_BUF_INIT;
/* Ensure a known loose ref can be looked up */
cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
cl_assert(git_reference_is_packed(reference) == 0);
cl_assert_strequal(reference->name, loose_tag_ref_name);
git_reference_free(reference);
/*
* We are now trying to pack also a loose reference
* called `points_to_blob`, to make sure we can properly
* pack weak tags
*/
cl_git_pass(git_reference_packall(g_repo));
/* Ensure the packed-refs file exists */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, GIT_PACKEDREFS_FILE));
cl_git_pass(git_path_exists(temp_path.ptr));
/* Ensure the known ref can still be looked up but is now packed */
cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
cl_assert(git_reference_is_packed(reference));
cl_assert_strequal(reference->name, loose_tag_ref_name);
/* Ensure the known ref has been removed from the loose folder structure */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, loose_tag_ref_name));
cl_git_pass(!git_path_exists(temp_path.ptr));
git_reference_free(reference);
git_buf_free(&temp_path);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *loose_tag_ref_name = "refs/tags/e90810b";
static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist";
static const char *head_tracker_sym_ref_name = "head-tracker";
static const char *current_head_target = "refs/heads/master";
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
static const char *packed_head_name = "refs/heads/packed";
static const char *packed_test_head_name = "refs/heads/packed-test";
static git_repository *g_repo;
void test_ref_read__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_ref_read__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_ref_read__loose_tag(void)
{
// lookup a loose tag reference
git_reference *reference;
git_object *object;
git_buf ref_name_from_tag_name = GIT_BUF_INIT;
cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name));
cl_assert(git_reference_type(reference) & GIT_REF_OID);
cl_assert(git_reference_is_packed(reference) == 0);
cl_assert_strequal(reference->name, loose_tag_ref_name);
cl_git_pass(git_object_lookup(&object, g_repo, git_reference_oid(reference), GIT_OBJ_ANY));
cl_assert(object != NULL);
cl_assert(git_object_type(object) == GIT_OBJ_TAG);
/* Ensure the name of the tag matches the name of the reference */
cl_git_pass(git_buf_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object)));
cl_assert_strequal(ref_name_from_tag_name.ptr, loose_tag_ref_name);
git_buf_free(&ref_name_from_tag_name);
git_object_free(object);
git_reference_free(reference);
}
void test_ref_read__nonexisting_tag(void)
{
// lookup a loose tag reference that doesn't exist
git_reference *reference;
cl_git_fail(git_reference_lookup(&reference, g_repo, non_existing_tag_ref_name));
git_reference_free(reference);
}
void test_ref_read__symbolic(void)
{
// lookup a symbolic reference
git_reference *reference, *resolved_ref;
git_object *object;
git_oid id;
cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE));
cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC);
cl_assert(git_reference_is_packed(reference) == 0);
cl_assert_strequal(reference->name, GIT_HEAD_FILE);
cl_git_pass(git_reference_resolve(&resolved_ref, reference));
cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID);
cl_git_pass(git_object_lookup(&object, g_repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
cl_assert(object != NULL);
cl_assert(git_object_type(object) == GIT_OBJ_COMMIT);
git_oid_fromstr(&id, current_master_tip);
cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_free(object);
git_reference_free(reference);
git_reference_free(resolved_ref);
}
void test_ref_read__nested_symbolic(void)
{
// lookup a nested symbolic reference
git_reference *reference, *resolved_ref;
git_object *object;
git_oid id;
cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name));
cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC);
cl_assert(git_reference_is_packed(reference) == 0);
cl_assert_strequal(reference->name, head_tracker_sym_ref_name);
cl_git_pass(git_reference_resolve(&resolved_ref, reference));
cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID);
cl_git_pass(git_object_lookup(&object, g_repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
cl_assert(object != NULL);
cl_assert(git_object_type(object) == GIT_OBJ_COMMIT);
git_oid_fromstr(&id, current_master_tip);
cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_free(object);
git_reference_free(reference);
git_reference_free(resolved_ref);
}
void test_ref_read__head_then_master(void)
{
// lookup the HEAD and resolve the master branch
git_reference *reference, *resolved_ref, *comp_base_ref;
cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name));
cl_git_pass(git_reference_resolve(&comp_base_ref, reference));
git_reference_free(reference);
cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE));
cl_git_pass(git_reference_resolve(&resolved_ref, reference));
cl_git_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
git_reference_free(reference);
git_reference_free(resolved_ref);
cl_git_pass(git_reference_lookup(&reference, g_repo, current_head_target));
cl_git_pass(git_reference_resolve(&resolved_ref, reference));
cl_git_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
git_reference_free(reference);
git_reference_free(resolved_ref);
git_reference_free(comp_base_ref);
}
void test_ref_read__master_then_head(void)
{
// lookup the master branch and then the HEAD
git_reference *reference, *master_ref, *resolved_ref;
cl_git_pass(git_reference_lookup(&master_ref, g_repo, current_head_target));
cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE));
cl_git_pass(git_reference_resolve(&resolved_ref, reference));
cl_git_pass(git_oid_cmp(git_reference_oid(master_ref), git_reference_oid(resolved_ref)));
git_reference_free(reference);
git_reference_free(resolved_ref);
git_reference_free(master_ref);
}
void test_ref_read__packed(void)
{
// lookup a packed reference
git_reference *reference;
git_object *object;
cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name));
cl_assert(git_reference_type(reference) & GIT_REF_OID);
cl_assert(git_reference_is_packed(reference));
cl_assert_strequal(reference->name, packed_head_name);
cl_git_pass(git_object_lookup(&object, g_repo, git_reference_oid(reference), GIT_OBJ_ANY));
cl_assert(object != NULL);
cl_assert(git_object_type(object) == GIT_OBJ_COMMIT);
git_object_free(object);
git_reference_free(reference);
}
void test_ref_read__loose_first(void)
{
// assure that a loose reference is looked up before a packed reference
git_reference *reference;
cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name));
git_reference_free(reference);
cl_git_pass(git_reference_lookup(&reference, g_repo, packed_test_head_name));
cl_assert(git_reference_type(reference) & GIT_REF_OID);
cl_assert(git_reference_is_packed(reference) == 0);
cl_assert_strequal(reference->name, packed_test_head_name);
git_reference_free(reference);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *new_ref = "refs/heads/test-reflog";
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
static const char *commit_msg = "commit: bla bla";
static git_repository *g_repo;
// helpers
static void assert_signature(git_signature *expected, git_signature *actual)
{
cl_assert(actual);
cl_assert_strequal(expected->name, actual->name);
cl_assert_strequal(expected->email, actual->email);
cl_assert(expected->when.offset == actual->when.offset);
cl_assert(expected->when.time == actual->when.time);
}
// Fixture setup and teardown
void test_refs_reflog__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_refs_reflog__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refs_reflog__write_then_read(void)
{
// write a reflog for a given reference and ensure it can be read back
git_repository *repo2;
git_reference *ref, *lookedup_ref;
git_oid oid;
git_signature *committer;
git_reflog *reflog;
git_reflog_entry *entry;
char oid_str[GIT_OID_HEXSZ+1];
/* Create a new branch pointing at the HEAD */
git_oid_fromstr(&oid, current_master_tip);
cl_git_pass(git_reference_create_oid(&ref, g_repo, new_ref, &oid, 0));
git_reference_free(ref);
cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref));
cl_git_pass(git_signature_now(&committer, "foo", "foo@bar"));
cl_git_pass(git_reflog_write(ref, NULL, committer, NULL));
cl_git_fail(git_reflog_write(ref, NULL, committer, "no ancestor NULL for an existing reflog"));
cl_git_fail(git_reflog_write(ref, NULL, committer, "no\nnewline"));
cl_git_pass(git_reflog_write(ref, &oid, committer, commit_msg));
/* Reopen a new instance of the repository */
cl_git_pass(git_repository_open(&repo2, "testrepo"));
/* Lookup the preivously created branch */
cl_git_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref));
/* Read and parse the reflog for this branch */
cl_git_pass(git_reflog_read(&reflog, lookedup_ref));
cl_assert(reflog->entries.length == 2);
entry = (git_reflog_entry *)git_vector_get(&reflog->entries, 0);
assert_signature(committer, entry->committer);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_old);
cl_assert_strequal("0000000000000000000000000000000000000000", oid_str);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_cur);
cl_assert_strequal(current_master_tip, oid_str);
cl_assert(entry->msg == NULL);
entry = (git_reflog_entry *)git_vector_get(&reflog->entries, 1);
assert_signature(committer, entry->committer);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_old);
cl_assert_strequal(current_master_tip, oid_str);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_cur);
cl_assert_strequal(current_master_tip, oid_str);
cl_assert_strequal(commit_msg, entry->msg);
git_signature_free(committer);
git_reflog_free(reflog);
git_repository_free(repo2);
git_reference_free(ref);
git_reference_free(lookedup_ref);
}
void test_refs_reflog__dont_write_bad(void)
{
// avoid writing an obviously wrong reflog
git_reference *ref;
git_oid oid;
git_signature *committer;
/* Create a new branch pointing at the HEAD */
git_oid_fromstr(&oid, current_master_tip);
cl_git_pass(git_reference_create_oid(&ref, g_repo, new_ref, &oid, 0));
git_reference_free(ref);
cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref));
cl_git_pass(git_signature_now(&committer, "foo", "foo@bar"));
/* Write the reflog for the new branch */
cl_git_pass(git_reflog_write(ref, NULL, committer, NULL));
/* Try to update the reflog with wrong information:
* It's no new reference, so the ancestor OID cannot
* be NULL. */
cl_git_fail(git_reflog_write(ref, NULL, committer, NULL));
git_signature_free(committer);
git_reference_free(ref);
}
#include "clar_libgit2.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *loose_tag_ref_name = "refs/tags/e90810b";
static const char *packed_head_name = "refs/heads/packed";
static const char *packed_test_head_name = "refs/heads/packed-test";
static const char *ref_one_name = "refs/heads/one/branch";
static const char *ref_one_name_new = "refs/heads/two/branch";
static const char *ref_two_name = "refs/heads/two";
static const char *ref_master_name = "refs/heads/master";
static const char *ref_two_name_new = "refs/heads/two/two";
static git_repository *g_repo;
void test_refs_rename__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
}
void test_refs_rename__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refs_rename__loose(void)
{
// rename a loose reference
git_reference *looked_up_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu";
/* Ensure the ref doesn't exist on the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, new_name));
cl_git_pass(!git_path_exists(temp_path.ptr));
/* Retrieval of the reference to rename */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, loose_tag_ref_name));
/* ... which is indeed loose */
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(looked_up_ref, new_name, 0));
cl_assert_strequal(looked_up_ref->name, new_name);
/* ...It can't be looked-up with the old name... */
cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, loose_tag_ref_name));
/* ...but the new name works ok... */
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, new_name));
cl_assert_strequal(another_looked_up_ref->name, new_name);
/* .. the ref is still loose... */
cl_assert(git_reference_is_packed(another_looked_up_ref) == 0);
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref can be found in the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, new_name));
cl_git_pass(git_path_exists(temp_path.ptr));
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__packed(void)
{
// rename a packed reference (should make it loose)
git_reference *looked_up_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
/* Ensure the ref doesn't exist on the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, packed_head_name));
cl_git_pass(!git_path_exists(temp_path.ptr));
/* The reference can however be looked-up... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
/* .. and it's packed */
cl_assert(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
cl_assert_strequal(looked_up_ref->name, brand_new_name);
/* ...It can't be looked-up with the old name... */
cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_head_name));
/* ...but the new name works ok... */
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, brand_new_name));
cl_assert_strequal(another_looked_up_ref->name, brand_new_name);
/* .. the ref is no longer packed... */
cl_assert(git_reference_is_packed(another_looked_up_ref) == 0);
cl_assert(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref now happily lives in the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, brand_new_name));
cl_git_pass(git_path_exists(temp_path.ptr));
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__packed_doesnt_pack_others(void)
{
// renaming a packed reference does not pack another reference which happens to be in both loose and pack state
git_reference *looked_up_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
/* Ensure the other reference exists on the file system */
cl_git_pass(git_buf_joinpath(&temp_path, g_repo->path_repository, packed_test_head_name));
cl_git_pass(git_path_exists(temp_path.ptr));
/* Lookup the other reference */
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
/* Ensure it's loose */
cl_assert(git_reference_is_packed(another_looked_up_ref) == 0);
git_reference_free(another_looked_up_ref);
/* Lookup the reference to rename */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
/* Ensure it's packed */
cl_assert(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
/* Lookup the other reference */
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
/* Ensure it's loose */
cl_assert(git_reference_is_packed(another_looked_up_ref) == 0);
/* Ensure the other ref still exists on the file system */
cl_git_pass(git_path_exists(temp_path.ptr));
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__name_collision(void)
{
// can not rename a reference with the name of an existing reference
git_reference *looked_up_ref;
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
/* Can not be renamed to the name of another existing reference. */
cl_git_fail(git_reference_rename(looked_up_ref, packed_test_head_name, 0));
git_reference_free(looked_up_ref);
/* Failure to rename it hasn't corrupted its state */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
cl_assert_strequal(looked_up_ref->name, packed_head_name);
git_reference_free(looked_up_ref);
}
void test_refs_rename__invalid_name(void)
{
// can not rename a reference with an invalid name
git_reference *looked_up_ref;
/* An existing oid reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
/* Can not be renamed with an invalid name. */
cl_git_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
/* Can not be renamed outside of the refs hierarchy. */
cl_git_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
/* Failure to rename it hasn't corrupted its state */
git_reference_free(looked_up_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
cl_assert_strequal(looked_up_ref->name, packed_test_head_name);
git_reference_free(looked_up_ref);
}
void test_refs_rename__force_loose_packed(void)
{
// can force-rename a packed reference with the name of an existing loose and packed reference
git_reference *looked_up_ref;
git_oid oid;
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
git_oid_cpy(&oid, git_reference_oid(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
cl_git_pass(git_reference_rename(looked_up_ref, packed_test_head_name, 1));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
cl_assert_strequal(looked_up_ref->name, packed_test_head_name);
cl_assert(!git_oid_cmp(&oid, git_reference_oid(looked_up_ref)));
git_reference_free(looked_up_ref);
/* And that the previous one doesn't exist any longer */
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
}
void test_refs_rename__force_loose(void)
{
// can force-rename a loose reference with the name of an existing loose reference
git_reference *looked_up_ref;
git_oid oid;
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2"));
git_oid_cpy(&oid, git_reference_oid(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
cl_git_pass(git_reference_rename(looked_up_ref, "refs/heads/test", 1));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/test"));
cl_assert_strequal(looked_up_ref->name, "refs/heads/test");
cl_assert(!git_oid_cmp(&oid, git_reference_oid(looked_up_ref)));
git_reference_free(looked_up_ref);
/* And that the previous one doesn't exist any longer */
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2"));
git_reference_free(looked_up_ref);
}
void test_refs_rename__overwrite(void)
{
// can not overwrite name of existing reference
git_reference *ref, *ref_one, *ref_one_new, *ref_two;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
cl_git_pass(git_reference_create_oid(&ref_one, g_repo, ref_one_name, &id, 0));
cl_git_pass(git_reference_create_oid(&ref_two, g_repo, ref_two_name, &id, 0));
/* Pack everything */
cl_git_pass(git_reference_packall(g_repo));
/* Attempt to create illegal reference */
cl_git_fail(git_reference_create_oid(&ref_one_new, g_repo, ref_one_name_new, &id, 0));
/* Illegal reference couldn't be created so this is supposed to fail */
cl_git_fail(git_reference_lookup(&ref_one_new, g_repo, ref_one_name_new));
git_reference_free(ref);
git_reference_free(ref_one);
git_reference_free(ref_one_new);
git_reference_free(ref_two);
}
void test_refs_rename__prefix(void)
{
// can be renamed to a new name prefixed with the old name
git_reference *ref, *ref_two, *looked_up_ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
cl_git_pass(git_reference_create_oid(&ref_two, g_repo, ref_two_name, &id, 0));
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
/* Can be rename to a new name starting with the old name. */
cl_git_pass(git_reference_rename(looked_up_ref, ref_two_name_new, 0));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
cl_assert_strequal(looked_up_ref->name, ref_two_name_new);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
git_reference_free(ref);
git_reference_free(ref_two);
git_reference_free(looked_up_ref);
}
void test_refs_rename__move_up(void)
{
// can move a reference to a upper reference hierarchy
git_reference *ref, *ref_two, *looked_up_ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
cl_git_pass(git_reference_create_oid(&ref_two, g_repo, ref_two_name_new, &id, 0));
git_reference_free(ref_two);
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
/* Can be renamed upward the reference tree. */
cl_git_pass(git_reference_rename(looked_up_ref, ref_two_name, 0));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
cl_assert_strequal(looked_up_ref->name, ref_two_name);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
git_reference_free(ref);
git_reference_free(looked_up_ref);
}
#include "clar_libgit2.h"
#include "odb.h"
#include "repository.h"
#define TEMP_REPO_FOLDER "temprepo/"
#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git"
#define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME
#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub"
#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub"
#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub"
#define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo"
#define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub"
#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub"
#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub"
#define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1"
#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2"
#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3"
#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo"
static void ensure_repository_discover(const char *start_path,
const char *ceiling_dirs,
const char *expected_path)
{
char found_path[GIT_PATH_MAX];
cl_git_pass(git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs));
//across_fs is always 0 as we can't automate the filesystem change tests
cl_assert_strequal(found_path, expected_path);
}
static void write_file(const char *path, const char *content)
{
git_file file;
int error;
if (git_path_exists(path) == GIT_SUCCESS) {
cl_git_pass(p_unlink(path));
}
file = git_futils_creat_withpath(path, 0777, 0666);
cl_assert(file >= 0);
error = p_write(file, content, strlen(content) * sizeof(char));
p_close(file);
cl_git_pass(error);
}
//no check is performed on ceiling_dirs length, so be sure it's long enough
static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
{
git_buf pretty_path = GIT_BUF_INIT;
char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' };
cl_git_pass(git_path_prettify_dir(&pretty_path, path, NULL));
if (ceiling_dirs->size > 0)
git_buf_puts(ceiling_dirs, ceiling_separator);
git_buf_puts(ceiling_dirs, pretty_path.ptr);
git_buf_free(&pretty_path);
cl_git_pass(git_buf_lasterror(ceiling_dirs));
}
void test_repo_discover__0(void)
{
// test discover
git_repository *repo;
git_buf ceiling_dirs_buf = GIT_BUF_INIT;
const char *ceiling_dirs;
char repository_path[GIT_PATH_MAX];
char sub_repository_path[GIT_PATH_MAX];
char found_path[GIT_PATH_MAX];
const mode_t mode = 0777;
git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode);
append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
cl_assert(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO);
cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
git_repository_free(repo);
cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path);
cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode));
write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../");
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode));
write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:");
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, NULL, mode));
write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:");
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, NULL, mode));
write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n");
cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode));
write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist");
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
cl_git_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
//.gitfile redirection should not be affected by ceiling directories
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);
cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
git_repository_free(repo);
git_buf_free(&ceiling_dirs_buf);
}
a4a7dce85cf63874e984719f4fdd239f5145052f
a65fedf39aefe402d3bb6e24df4d4f5fe4547750
4a202b346bb0fb0db7eff3cffeb3c70babbd2045
763d71aadf09a7951596c9746c024e7eece7c7af
e90810b8df3e80c413d903f631643c716887138d
7b4384978d2493e851f9cca7858815fac9b10980
1385f264afb75a56a5bec74243be9b367ba4ca08
b25fa35b38051e4ae45d4222e795f9df2e43f1d1
[core]
repositoryformatversion = 0
filemode = true
bare = true
logallrefupdates = true
[remote "test"]
url = git://github.com/libgit2/libgit2
fetch = +refs/heads/*:refs/remotes/test/*
# pack-refs with: peeled
41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 refs/heads/packed
5b5b025afb0b4c913b4c338a42934a3863bf3644 refs/heads/packed-test
a4a7dce85cf63874e984719f4fdd239f5145052f
a65fedf39aefe402d3bb6e24df4d4f5fe4547750
763d71aadf09a7951596c9746c024e7eece7c7af
e90810b8df3e80c413d903f631643c716887138d
7b4384978d2493e851f9cca7858815fac9b10980
b25fa35b38051e4ae45d4222e795f9df2e43f1d1
#include "clar_libgit2.h"
#include "cache.h"
static git_repository *g_repo;
void test_threads_basic__initialize(void) {
g_repo = cl_git_sandbox_init("testrepo");
}
void test_threads_basic__cleanup(void) {
cl_git_sandbox_cleanup();
}
void test_threads_basic__cache(void) {
// run several threads polling the cache at the same time
cl_assert(1 == 1);
}
Test sources should be named:
t????-function.c
where ???? is a four digit code. The first two digits classify
the test into a major category; the final two digits indicate the
sequence of the test within that category. The function part of
the test name should give a rough indication of what it does.
Categories
----------
00__: Core library routines based only on the standard library,
and that are essential for everything else to run. E.g.
errno and malloc.
01__: Basic hashing functions, needed to handle the content
addressable store.
02__: Basic object read access.
03__: Basic object writing.
04__: Parsing and loading commit data
05__: Revision walking
06__: Index reading, writing and searching
07__: Tests for the internal hashtable code
08__: Tag reading and writing
09__: Reading tree objects
10__: Symbolic, loose and packed references reading and writing.
11__: SQLite backend
12__: Repository init and opening
13__: Threads, empty as of now
14__: Redis backend
15__: Configuration parsing
16__: Remotes
17__: Buffers
18__: File Status
a4a7dce85cf63874e984719f4fdd239f5145052f
a65fedf39aefe402d3bb6e24df4d4f5fe4547750
763d71aadf09a7951596c9746c024e7eece7c7af
e90810b8df3e80c413d903f631643c716887138d
7b4384978d2493e851f9cca7858815fac9b10980
b25fa35b38051e4ae45d4222e795f9df2e43f1d1
/*
* 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 "test_lib.h"
#include "vector.h"
#include "fileops.h"
#include "filebuf.h"
BEGIN_TEST(string0, "compare prefixes")
must_be_true(git__prefixcmp("", "") == 0);
must_be_true(git__prefixcmp("a", "") == 0);
must_be_true(git__prefixcmp("", "a") < 0);
must_be_true(git__prefixcmp("a", "b") < 0);
must_be_true(git__prefixcmp("b", "a") > 0);
must_be_true(git__prefixcmp("ab", "a") == 0);
must_be_true(git__prefixcmp("ab", "ac") < 0);
must_be_true(git__prefixcmp("ab", "aa") > 0);
END_TEST
BEGIN_TEST(string1, "compare suffixes")
must_be_true(git__suffixcmp("", "") == 0);
must_be_true(git__suffixcmp("a", "") == 0);
must_be_true(git__suffixcmp("", "a") < 0);
must_be_true(git__suffixcmp("a", "b") < 0);
must_be_true(git__suffixcmp("b", "a") > 0);
must_be_true(git__suffixcmp("ba", "a") == 0);
must_be_true(git__suffixcmp("zaa", "ac") < 0);
must_be_true(git__suffixcmp("zaz", "ac") > 0);
END_TEST
BEGIN_TEST(vector0, "initial size of 1 would cause writing past array bounds")
git_vector x;
int i;
git_vector_init(&x, 1, NULL);
for (i = 0; i < 10; ++i) {
git_vector_insert(&x, (void*) 0xabc);
}
git_vector_free(&x);
END_TEST
BEGIN_TEST(vector1, "don't read past array bounds on remove()")
git_vector x;
// make initial capacity exact for our insertions.
git_vector_init(&x, 3, NULL);
git_vector_insert(&x, (void*) 0xabc);
git_vector_insert(&x, (void*) 0xdef);
git_vector_insert(&x, (void*) 0x123);
git_vector_remove(&x, 0); // used to read past array bounds.
git_vector_free(&x);
END_TEST
static int test_cmp(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
BEGIN_TEST(vector2, "remove duplicates")
git_vector x;
int *ptrs[2];
ptrs[0] = git__malloc(sizeof(int));
ptrs[1] = git__malloc(sizeof(int));
*ptrs[0] = 2;
*ptrs[1] = 1;
must_pass(git_vector_init(&x, 5, test_cmp));
must_pass(git_vector_insert(&x, ptrs[0]));
must_pass(git_vector_insert(&x, ptrs[1]));
must_pass(git_vector_insert(&x, ptrs[1]));
must_pass(git_vector_insert(&x, ptrs[0]));
must_pass(git_vector_insert(&x, ptrs[1]));
must_be_true(x.length == 5);
git_vector_uniq(&x);
must_be_true(x.length == 2);
git_vector_free(&x);
git__free(ptrs[0]);
git__free(ptrs[1]);
END_TEST
BEGIN_TEST(path0, "get the dirname of a path")
git_buf dir = GIT_BUF_INIT;
char *dir2;
#define DIRNAME_TEST(A, B) { \
must_be_true(git_path_dirname_r(&dir, A) >= 0); \
must_be_true(strcmp(B, dir.ptr) == 0); \
must_be_true((dir2 = git_path_dirname(A)) != NULL); \
must_be_true(strcmp(dir2, B) == 0); \
git__free(dir2); \
}
DIRNAME_TEST(NULL, ".");
DIRNAME_TEST("", ".");
DIRNAME_TEST("a", ".");
DIRNAME_TEST("/", "/");
DIRNAME_TEST("/usr", "/");
DIRNAME_TEST("/usr/", "/");
DIRNAME_TEST("/usr/lib", "/usr");
DIRNAME_TEST("/usr/lib/", "/usr");
DIRNAME_TEST("/usr/lib//", "/usr");
DIRNAME_TEST("usr/lib", "usr");
DIRNAME_TEST("usr/lib/", "usr");
DIRNAME_TEST("usr/lib//", "usr");
DIRNAME_TEST(".git/", ".");
#undef DIRNAME_TEST
git_buf_free(&dir);
END_TEST
BEGIN_TEST(path1, "get the base name of a path")
git_buf base = GIT_BUF_INIT;
char *base2;
#define BASENAME_TEST(A, B) { \
must_be_true(git_path_basename_r(&base, A) >= 0); \
must_be_true(strcmp(B, base.ptr) == 0); \
must_be_true((base2 = git_path_basename(A)) != NULL); \
must_be_true(strcmp(base2, B) == 0); \
git__free(base2); \
}
BASENAME_TEST(NULL, ".");
BASENAME_TEST("", ".");
BASENAME_TEST("a", "a");
BASENAME_TEST("/", "/");
BASENAME_TEST("/usr", "usr");
BASENAME_TEST("/usr/", "usr");
BASENAME_TEST("/usr/lib", "lib");
BASENAME_TEST("/usr/lib//", "lib");
BASENAME_TEST("usr/lib", "lib");
#undef BASENAME_TEST
git_buf_free(&base);
END_TEST
BEGIN_TEST(path2, "get the latest component in a path")
const char *dir;
#define TOPDIR_TEST(A, B) { \
must_be_true((dir = git_path_topdir(A)) != NULL); \
must_be_true(strcmp(dir, B) == 0); \
}
TOPDIR_TEST(".git/", ".git/");
TOPDIR_TEST("/.git/", ".git/");
TOPDIR_TEST("usr/local/.git/", ".git/");
TOPDIR_TEST("./.git/", ".git/");
TOPDIR_TEST("/usr/.git/", ".git/");
TOPDIR_TEST("/", "/");
TOPDIR_TEST("a/", "a/");
must_be_true(git_path_topdir("/usr/.git") == NULL);
must_be_true(git_path_topdir(".") == NULL);
must_be_true(git_path_topdir("") == NULL);
must_be_true(git_path_topdir("a") == NULL);
#undef TOPDIR_TEST
END_TEST
static int ensure_joinpath(const char *path_a, const char *path_b, const char *expected_path)
{
int error = GIT_SUCCESS;
git_buf joined_path = GIT_BUF_INIT;
if (!(error = git_buf_joinpath(&joined_path, path_a, path_b)))
error = strcmp(joined_path.ptr, expected_path) == 0 ?
GIT_SUCCESS : GIT_ERROR;
git_buf_free(&joined_path);
return error;
}
BEGIN_TEST(path5, "properly join path components")
must_pass(ensure_joinpath("", "", ""));
must_pass(ensure_joinpath("", "a", "a"));
must_pass(ensure_joinpath("", "/a", "/a"));
must_pass(ensure_joinpath("a", "", "a/"));
must_pass(ensure_joinpath("a", "/", "a/"));
must_pass(ensure_joinpath("a", "b", "a/b"));
must_pass(ensure_joinpath("/", "a", "/a"));
must_pass(ensure_joinpath("/", "", "/"));
must_pass(ensure_joinpath("/a", "/b", "/a/b"));
must_pass(ensure_joinpath("/a", "/b/", "/a/b/"));
must_pass(ensure_joinpath("/a/", "b/", "/a/b/"));
must_pass(ensure_joinpath("/a/", "/b/", "/a/b/"));
END_TEST
static int ensure_joinpath_n(const char *path_a, const char *path_b, const char *path_c, const char *path_d, const char *expected_path)
{
int error = GIT_SUCCESS;
git_buf joined_path = GIT_BUF_INIT;
if (!(error = git_buf_join_n(&joined_path, '/', 4,
path_a, path_b, path_c, path_d)))
error = strcmp(joined_path.ptr, expected_path) == 0 ?
GIT_SUCCESS : GIT_ERROR;
git_buf_free(&joined_path);
return error;
}
BEGIN_TEST(path6, "properly join path components for more than one path")
must_pass(ensure_joinpath_n("", "", "", "", ""));
must_pass(ensure_joinpath_n("", "a", "", "", "a/"));
must_pass(ensure_joinpath_n("a", "", "", "", "a/"));
must_pass(ensure_joinpath_n("", "", "", "a", "a"));
must_pass(ensure_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/"));
must_pass(ensure_joinpath_n("a", "b", "", "/c/d", "a/b/c/d"));
END_TEST
typedef struct name_data {
int count; /* return count */
char *name; /* filename */
} name_data;
typedef struct walk_data {
char *sub; /* sub-directory name */
name_data *names; /* name state data */
git_buf path; /* buffer to store path */
} walk_data;
static char *top_dir = "dir-walk";
static walk_data *state_loc;
static int error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
return -1;
}
static int setup(walk_data *d)
{
name_data *n;
if (p_mkdir(top_dir, 0777) < 0)
return error("can't mkdir(\"%s\")", top_dir);
if (p_chdir(top_dir) < 0)
return error("can't chdir(\"%s\")", top_dir);
if (strcmp(d->sub, ".") != 0)
if (p_mkdir(d->sub, 0777) < 0)
return error("can't mkdir(\"%s\")", d->sub);
if (git_buf_sets(&d->path, d->sub) < 0)
return error("can't allocate space for \"%s\"", d->sub);
state_loc = d;
for (n = d->names; n->name; n++) {
git_file fd = p_creat(n->name, 0666);
if (fd < 0)
return GIT_ERROR;
p_close(fd);
n->count = 0;
}
return 0;
}
static int knockdown(walk_data *d)
{
name_data *n;
git_buf_free(&d->path);
for (n = d->names; n->name; n++) {
if (p_unlink(n->name) < 0)
return error("can't unlink(\"%s\")", n->name);
}
if (strcmp(d->sub, ".") != 0)
if (p_rmdir(d->sub) < 0)
return error("can't rmdir(\"%s\")", d->sub);
if (p_chdir("..") < 0)
return error("can't chdir(\"..\")");
if (p_rmdir(top_dir) < 0)
return error("can't rmdir(\"%s\")", top_dir);
return 0;
}
static int check_counts(walk_data *d)
{
int ret = 0;
name_data *n;
for (n = d->names; n->name; n++) {
if (n->count != 1)
ret = error("count (%d, %s)", n->count, n->name);
}
return ret;
}
static int one_entry(void *state, git_buf *path)
{
walk_data *d = (walk_data *) state;
name_data *n;
if (state != state_loc)
return GIT_ERROR;
if (path != &d->path)
return GIT_ERROR;
for (n = d->names; n->name; n++) {
if (!strcmp(n->name, path->ptr)) {
n->count++;
return 0;
}
}
return GIT_ERROR;
}
static name_data dot_names[] = {
{ 0, "./a" },
{ 0, "./asdf" },
{ 0, "./pack-foo.pack" },
{ 0, NULL }
};
static walk_data dot = {
".",
dot_names,
GIT_BUF_INIT
};
BEGIN_TEST(dirent0, "make sure that the '.' folder is not traversed")
must_pass(setup(&dot));
must_pass(git_path_direach(&dot.path,
one_entry,
&dot));
must_pass(check_counts(&dot));
must_pass(knockdown(&dot));
END_TEST
static name_data sub_names[] = {
{ 0, "sub/a" },
{ 0, "sub/asdf" },
{ 0, "sub/pack-foo.pack" },
{ 0, NULL }
};
static walk_data sub = {
"sub",
sub_names,
GIT_BUF_INIT
};
BEGIN_TEST(dirent1, "traverse a subfolder")
must_pass(setup(&sub));
must_pass(git_path_direach(&sub.path,
one_entry,
&sub));
must_pass(check_counts(&sub));
must_pass(knockdown(&sub));
END_TEST
static walk_data sub_slash = {
"sub/",
sub_names,
GIT_BUF_INIT
};
BEGIN_TEST(dirent2, "traverse a slash-terminated subfolder")
must_pass(setup(&sub_slash));
must_pass(git_path_direach(&sub_slash.path,
one_entry,
&sub_slash));
must_pass(check_counts(&sub_slash));
must_pass(knockdown(&sub_slash));
END_TEST
static name_data empty_names[] = {
{ 0, NULL }
};
static walk_data empty = {
"empty",
empty_names,
GIT_BUF_INIT
};
static int dont_call_me(void *state, git_buf *path)
{
GIT_UNUSED(state);
GIT_UNUSED(path);
return GIT_ERROR;
}
BEGIN_TEST(dirent3, "make sure that empty folders are not traversed")
must_pass(setup(&empty));
must_pass(git_path_direach(&empty.path,
one_entry,
&empty));
must_pass(check_counts(&empty));
/* make sure callback not called */
must_pass(git_path_direach(&empty.path,
dont_call_me,
&empty));
must_pass(knockdown(&empty));
END_TEST
static name_data odd_names[] = {
{ 0, "odd/.a" },
{ 0, "odd/..c" },
/* the following don't work on cygwin/win32 */
/* { 0, "odd/.b." }, */
/* { 0, "odd/..d.." }, */
{ 0, NULL }
};
static walk_data odd = {
"odd",
odd_names,
GIT_BUF_INIT
};
BEGIN_TEST(dirent4, "make sure that strange looking filenames ('..c') are traversed")
must_pass(setup(&odd));
must_pass(git_path_direach(&odd.path,
one_entry,
&odd));
must_pass(check_counts(&odd));
must_pass(knockdown(&odd));
END_TEST
BEGIN_TEST(filebuf0, "make sure git_filebuf_open doesn't delete an existing lock")
git_filebuf file = GIT_FILEBUF_INIT;
int fd;
char test[] = "test", testlock[] = "test.lock";
fd = p_creat(testlock, 0744);
must_pass(fd);
must_pass(p_close(fd));
must_fail(git_filebuf_open(&file, test, 0));
must_pass(git_path_exists(testlock));
must_pass(p_unlink(testlock));
END_TEST
BEGIN_TEST(filebuf1, "make sure GIT_FILEBUF_APPEND works as expected")
git_filebuf file = GIT_FILEBUF_INIT;
int fd;
char test[] = "test";
fd = p_creat(test, 0666);
must_pass(fd);
must_pass(p_write(fd, "libgit2 rocks\n", 14));
must_pass(p_close(fd));
must_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND));
must_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
must_pass(git_filebuf_commit(&file, 0666));
must_pass(p_unlink(test));
END_TEST
BEGIN_TEST(filebuf2, "make sure git_filebuf_write writes large buffer correctly")
git_filebuf file = GIT_FILEBUF_INIT;
char test[] = "test";
unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */
memset(buf, 0xfe, sizeof(buf));
must_pass(git_filebuf_open(&file, test, 0));
must_pass(git_filebuf_write(&file, buf, sizeof(buf)));
must_pass(git_filebuf_commit(&file, 0666));
must_pass(p_unlink(test));
END_TEST
static char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test";
static int setup_empty_tmp_dir(void)
{
git_buf path = GIT_BUF_INIT;
int error =
p_mkdir(empty_tmp_dir, 0777) ||
git_buf_joinpath(&path, empty_tmp_dir, "/one") ||
p_mkdir(path.ptr, 0777) ||
git_buf_joinpath(&path, empty_tmp_dir, "/one/two_one") ||
p_mkdir(path.ptr, 0777) ||
git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two") ||
p_mkdir(path.ptr, 0777) ||
git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two/three") ||
p_mkdir(path.ptr, 0777) ||
git_buf_joinpath(&path, empty_tmp_dir, "/two") ||
p_mkdir(path.ptr, 0777);
git_buf_free(&path);
return error ? -1 : 0;
}
BEGIN_TEST(rmdir0, "make sure empty dir can be deleted recusively")
must_pass(setup_empty_tmp_dir());
must_pass(git_futils_rmdir_r(empty_tmp_dir, 0));
END_TEST
BEGIN_TEST(rmdir1, "make sure non-empty dir cannot be deleted recusively")
git_buf file = GIT_BUF_INIT;
int fd;
must_pass(setup_empty_tmp_dir());
must_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt"));
fd = p_creat(file.ptr, 0777);
must_pass(fd);
must_pass(p_close(fd));
must_fail(git_futils_rmdir_r(empty_tmp_dir, 0));
must_pass(p_unlink(file.ptr));
must_pass(git_futils_rmdir_r(empty_tmp_dir, 0));
git_buf_free(&file);
END_TEST
BEGIN_TEST(strtol0, "parsing out 32 integers from a string")
int32_t i;
must_pass(git__strtol32(&i, "123", NULL, 10));
must_be_true(i == 123);
must_pass(git__strtol32(&i, " +123 ", NULL, 10));
must_be_true(i == 123);
must_pass(git__strtol32(&i, " +2147483647 ", NULL, 10));
must_be_true(i == 2147483647);
must_pass(git__strtol32(&i, " -2147483648 ", NULL, 10));
must_be_true(i == -2147483648LL);
must_fail(git__strtol32(&i, " 2147483657 ", NULL, 10));
must_fail(git__strtol32(&i, " -2147483657 ", NULL, 10));
END_TEST
BEGIN_TEST(strtol1, "parsing out 64 integers from a string")
int64_t i;
must_pass(git__strtol64(&i, "123", NULL, 10));
must_be_true(i == 123);
must_pass(git__strtol64(&i, " +123 ", NULL, 10));
must_be_true(i == 123);
must_pass(git__strtol64(&i, " +2147483647 ", NULL, 10));
must_be_true(i == 2147483647);
must_pass(git__strtol64(&i, " -2147483648 ", NULL, 10));
must_be_true(i == -2147483648LL);
must_pass(git__strtol64(&i, " 2147483657 ", NULL, 10));
must_be_true(i == 2147483657LL);
must_pass(git__strtol64(&i, " -2147483657 ", NULL, 10));
must_be_true(i == -2147483657LL);
END_TEST
BEGIN_SUITE(core)
ADD_TEST(string0);
ADD_TEST(string1);
ADD_TEST(vector0);
ADD_TEST(vector1);
ADD_TEST(vector2);
ADD_TEST(path0);
ADD_TEST(path1);
ADD_TEST(path2);
ADD_TEST(path5);
ADD_TEST(path6);
ADD_TEST(dirent0);
ADD_TEST(dirent1);
ADD_TEST(dirent2);
ADD_TEST(dirent3);
ADD_TEST(dirent4);
ADD_TEST(filebuf0);
ADD_TEST(filebuf1);
ADD_TEST(filebuf2);
ADD_TEST(rmdir0);
ADD_TEST(rmdir1);
ADD_TEST(strtol0);
ADD_TEST(strtol1);
END_SUITE
/*
* Raw data
*/
static unsigned char commit_data[] = {
0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x3e, 0x0a,
};
static unsigned char tree_data[] = {
0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
};
static unsigned char tag_data[] = {
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
0x2e, 0x30, 0x2e, 0x31, 0x0a,
};
static unsigned char zero_data[] = {
0x00 /* dummy data */
};
static unsigned char one_data[] = {
0x0a,
};
static unsigned char two_data[] = {
0x61, 0x0a,
};
static unsigned char some_data[] = {
0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
0x0a,
};
/*
* Sha1 IDS
*/
static char *commit_id = "3d7f8a6af076c8c3f20071a8935cdbe8228594d1";
static char *tree_id = "dff2da90b254e1beb889d1f1f1288be1803782df";
static char *tag_id = "09d373e1dfdc16b129ceec6dd649739911541e05";
static char *zero_id = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391";
static char *one_id = "8b137891791fe96927ad78e64b0aad7bded08bdc";
static char *two_id = "78981922613b2afb6025042ff6bd878ac1994e85";
static char *some_id = "fd8430bc864cfcd5f10e5590f8a447e01b942bfe";
/*
* In memory objects
*/
static git_rawobj tree_obj = {
tree_data,
sizeof(tree_data),
GIT_OBJ_TREE
};
static git_rawobj tag_obj = {
tag_data,
sizeof(tag_data),
GIT_OBJ_TAG
};
static git_rawobj zero_obj = {
zero_data,
0,
GIT_OBJ_BLOB
};
static git_rawobj one_obj = {
one_data,
sizeof(one_data),
GIT_OBJ_BLOB
};
static git_rawobj two_obj = {
two_data,
sizeof(two_data),
GIT_OBJ_BLOB
};
static git_rawobj commit_obj = {
commit_data,
sizeof(commit_data),
GIT_OBJ_COMMIT
};
static git_rawobj some_obj = {
some_data,
sizeof(some_data),
GIT_OBJ_BLOB
};
static git_rawobj junk_obj = {
NULL,
0,
GIT_OBJ_BAD
};
/*
* 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 "test_lib.h"
#include "odb.h"
#include "hash.h"
#include "t01-data.h"
static int hash_object(git_oid *oid, git_rawobj *obj)
{
return git_odb_hash(oid, obj->data, obj->len, obj->type);
}
BEGIN_TEST(oid0, "validate size of oid objects")
git_oid out;
must_be_true(20 == GIT_OID_RAWSZ);
must_be_true(40 == GIT_OID_HEXSZ);
must_be_true(sizeof(out) == GIT_OID_RAWSZ);
must_be_true(sizeof(out.id) == GIT_OID_RAWSZ);
END_TEST
BEGIN_TEST(oid1, "fail when parsing an empty string as oid")
git_oid out;
must_fail(git_oid_fromstr(&out, ""));
END_TEST
BEGIN_TEST(oid2, "fail when parsing an invalid string as oid")
git_oid out;
must_fail(git_oid_fromstr(&out, "moo"));
END_TEST
BEGIN_TEST(oid3, "find all invalid characters when parsing an oid")
git_oid out;
unsigned char exp[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
char in[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0";
unsigned int i;
for (i = 0; i < 256; i++) {
in[38] = (char)i;
if (git__fromhex(i) >= 0) {
exp[19] = (unsigned char)(git__fromhex(i) << 4);
must_pass(git_oid_fromstr(&out, in));
must_be_true(memcmp(out.id, exp, sizeof(out.id)) == 0);
} else {
must_fail(git_oid_fromstr(&out, in));
}
}
END_TEST
BEGIN_TEST(oid4, "fail when parsing an invalid oid string")
git_oid out;
must_fail(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5ez"));
END_TEST
BEGIN_TEST(oid5, "succeed when parsing a valid oid string")
git_oid out;
unsigned char exp[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
must_pass(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5e0"));
must_pass(memcmp(out.id, exp, sizeof(out.id)));
must_pass(git_oid_fromstr(&out, "16A67770B7D8D72317C4b775213C23A8BD74F5E0"));
must_pass(memcmp(out.id, exp, sizeof(out.id)));
END_TEST
BEGIN_TEST(oid6, "build a valid oid from raw bytes")
git_oid out;
unsigned char exp[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
git_oid_fromraw(&out, exp);
must_pass(memcmp(out.id, exp, sizeof(out.id)));
END_TEST
BEGIN_TEST(oid7, "properly copy an oid to another")
git_oid a, b;
unsigned char exp[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
memset(&b, 0, sizeof(b));
git_oid_fromraw(&a, exp);
git_oid_cpy(&b, &a);
must_pass(memcmp(a.id, exp, sizeof(a.id)));
END_TEST
BEGIN_TEST(oid8, "compare two oids (lesser than)")
git_oid a, b;
unsigned char a_in[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
unsigned char b_in[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xf0,
};
git_oid_fromraw(&a, a_in);
git_oid_fromraw(&b, b_in);
must_be_true(git_oid_cmp(&a, &b) < 0);
END_TEST
BEGIN_TEST(oid9, "compare two oids (equal)")
git_oid a, b;
unsigned char a_in[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
git_oid_fromraw(&a, a_in);
git_oid_fromraw(&b, a_in);
must_be_true(git_oid_cmp(&a, &b) == 0);
END_TEST
BEGIN_TEST(oid10, "compare two oids (greater than)")
git_oid a, b;
unsigned char a_in[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xe0,
};
unsigned char b_in[] = {
0x16, 0xa6, 0x77, 0x70, 0xb7,
0xd8, 0xd7, 0x23, 0x17, 0xc4,
0xb7, 0x75, 0x21, 0x3c, 0x23,
0xa8, 0xbd, 0x74, 0xf5, 0xd0,
};
git_oid_fromraw(&a, a_in);
git_oid_fromraw(&b, b_in);
must_be_true(git_oid_cmp(&a, &b) > 0);
END_TEST
BEGIN_TEST(oid11, "compare formated oids")
const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
char out[GIT_OID_HEXSZ + 1];
must_pass(git_oid_fromstr(&in, exp));
/* Format doesn't touch the last byte */
out[GIT_OID_HEXSZ] = 'Z';
git_oid_fmt(out, &in);
must_be_true(out[GIT_OID_HEXSZ] == 'Z');
/* Format produced the right result */
out[GIT_OID_HEXSZ] = '\0';
must_be_true(strcmp(exp, out) == 0);
END_TEST
BEGIN_TEST(oid12, "compare oids (allocate + format)")
const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
char *out;
must_pass(git_oid_fromstr(&in, exp));
out = git_oid_allocfmt(&in);
must_be_true(out);
must_be_true(strcmp(exp, out) == 0);
git__free(out);
END_TEST
BEGIN_TEST(oid13, "compare oids (path format)")
const char *exp1 = "16a0123456789abcdef4b775213c23a8bd74f5e0";
const char *exp2 = "16/a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
char out[GIT_OID_HEXSZ + 2];
must_pass(git_oid_fromstr(&in, exp1));
/* Format doesn't touch the last byte */
out[GIT_OID_HEXSZ + 1] = 'Z';
git_oid_pathfmt(out, &in);
must_be_true(out[GIT_OID_HEXSZ + 1] == 'Z');
/* Format produced the right result */
out[GIT_OID_HEXSZ + 1] = '\0';
must_be_true(strcmp(exp2, out) == 0);
END_TEST
BEGIN_TEST(oid14, "convert raw oid to string")
const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
char out[GIT_OID_HEXSZ + 1];
char *str;
int i;
must_pass(git_oid_fromstr(&in, exp));
/* NULL buffer pointer, returns static empty string */
str = git_oid_tostr(NULL, sizeof(out), &in);
must_be_true(str && *str == '\0' && str != out);
/* zero buffer size, returns static empty string */
str = git_oid_tostr(out, 0, &in);
must_be_true(str && *str == '\0' && str != out);
/* NULL oid pointer, returns static empty string */
str = git_oid_tostr(out, sizeof(out), NULL);
must_be_true(str && *str == '\0' && str != out);
/* n == 1, returns out as an empty string */
str = git_oid_tostr(out, 1, &in);
must_be_true(str && *str == '\0' && str == out);
for (i = 1; i < GIT_OID_HEXSZ; i++) {
out[i+1] = 'Z';
str = git_oid_tostr(out, i+1, &in);
/* returns out containing c-string */
must_be_true(str && str == out);
/* must be '\0' terminated */
must_be_true(*(str+i) == '\0');
/* must not touch bytes past end of string */
must_be_true(*(str+(i+1)) == 'Z');
/* i == n-1 charaters of string */
must_pass(strncmp(exp, out, i));
}
/* returns out as hex formatted c-string */
str = git_oid_tostr(out, sizeof(out), &in);
must_be_true(str && str == out && *(str+GIT_OID_HEXSZ) == '\0');
must_be_true(strcmp(exp, out) == 0);
END_TEST
BEGIN_TEST(oid15, "convert raw oid to string (big)")
const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0";
git_oid in;
char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */
char *str;
must_pass(git_oid_fromstr(&in, exp));
/* place some tail material */
big[GIT_OID_HEXSZ+0] = 'W'; /* should be '\0' afterwards */
big[GIT_OID_HEXSZ+1] = 'X'; /* should remain untouched */
big[GIT_OID_HEXSZ+2] = 'Y'; /* ditto */
big[GIT_OID_HEXSZ+3] = 'Z'; /* ditto */
/* returns big as hex formatted c-string */
str = git_oid_tostr(big, sizeof(big), &in);
must_be_true(str && str == big && *(str+GIT_OID_HEXSZ) == '\0');
must_be_true(strcmp(exp, big) == 0);
/* check tail material is untouched */
must_be_true(str && str == big && *(str+GIT_OID_HEXSZ+1) == 'X');
must_be_true(str && str == big && *(str+GIT_OID_HEXSZ+2) == 'Y');
must_be_true(str && str == big && *(str+GIT_OID_HEXSZ+3) == 'Z');
END_TEST
BEGIN_TEST(oid16, "make sure the OID shortener doesn't choke on duplicate sha1s")
git_oid_shorten *os;
int min_len;
os = git_oid_shorten_new(0);
must_be_true(os != NULL);
git_oid_shorten_add(os, "22596363b3de40b06f981fb85d82312e8c0ed511");
git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
git_oid_shorten_add(os, "16a0123456789abcdef4b775213c23a8bd74f5e0");
min_len = git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
must_be_true(min_len == GIT_OID_HEXSZ + 1);
git_oid_shorten_free(os);
END_TEST
BEGIN_TEST(oid17, "stress test for the git_oid_shorten object")
#define MAX_OIDS 1000
git_oid_shorten *os;
char *oids[MAX_OIDS];
char number_buffer[16];
git_oid oid;
size_t i, j;
int min_len = 0, found_collision;
os = git_oid_shorten_new(0);
must_be_true(os != NULL);
/*
* Insert in the shortener 1000 unique SHA1 ids
*/
for (i = 0; i < MAX_OIDS; ++i) {
char *oid_text;
sprintf(number_buffer, "%u", (unsigned int)i);
git_hash_buf(&oid, number_buffer, strlen(number_buffer));
oid_text = git__malloc(GIT_OID_HEXSZ + 1);
git_oid_fmt(oid_text, &oid);
oid_text[GIT_OID_HEXSZ] = 0;
min_len = git_oid_shorten_add(os, oid_text);
must_be_true(min_len >= 0);
oids[i] = oid_text;
}
/*
* Compare the first `min_char - 1` characters of each
* SHA1 OID. If the minimizer worked, we should find at
* least one collision
*/
found_collision = 0;
for (i = 0; i < MAX_OIDS; ++i) {
for (j = 0; j < MAX_OIDS; ++j) {
if (i != j && memcmp(oids[i], oids[j], min_len - 1) == 0)
found_collision = 1;
}
}
must_be_true(found_collision == 1);
/*
* Compare the first `min_char` characters of each
* SHA1 OID. If the minimizer worked, every single preffix
* should be unique.
*/
found_collision = 0;
for (i = 0; i < MAX_OIDS; ++i) {
for (j = 0; j < MAX_OIDS; ++j) {
if (i != j && memcmp(oids[i], oids[j], min_len) == 0)
found_collision = 1;
}
}
must_be_true(found_collision == 0);
/* cleanup */
for (i = 0; i < MAX_OIDS; ++i)
git__free(oids[i]);
git_oid_shorten_free(os);
#undef MAX_OIDS
END_TEST
static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511";
static char *hello_text = "hello world\n";
static char *bye_id = "ce08fe4884650f067bd5703b6a59a8b3b3c99a09";
static char *bye_text = "bye world\n";
BEGIN_TEST(hash0, "normal hash by blocks")
git_hash_ctx *ctx;
git_oid id1, id2;
must_be_true((ctx = git_hash_new_ctx()) != NULL);
/* should already be init'd */
git_hash_update(ctx, hello_text, strlen(hello_text));
git_hash_final(&id2, ctx);
must_pass(git_oid_fromstr(&id1, hello_id));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
/* reinit should permit reuse */
git_hash_init(ctx);
git_hash_update(ctx, bye_text, strlen(bye_text));
git_hash_final(&id2, ctx);
must_pass(git_oid_fromstr(&id1, bye_id));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
git_hash_free_ctx(ctx);
END_TEST
BEGIN_TEST(hash1, "hash whole buffer in a single call")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, hello_id));
git_hash_buf(&id2, hello_text, strlen(hello_text));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(hash2, "hash a vector")
git_oid id1, id2;
git_buf_vec vec[2];
must_pass(git_oid_fromstr(&id1, hello_id));
vec[0].data = hello_text;
vec[0].len = 4;
vec[1].data = hello_text+4;
vec[1].len = strlen(hello_text)-4;
git_hash_vec(&id2, vec, 2);
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objtype0, "convert type to string")
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_BAD), ""));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ__EXT1), ""));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_COMMIT), "commit"));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_TREE), "tree"));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_BLOB), "blob"));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_TAG), "tag"));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ__EXT2), ""));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"));
must_be_true(!strcmp(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA"));
must_be_true(!strcmp(git_object_type2string(-2), ""));
must_be_true(!strcmp(git_object_type2string(8), ""));
must_be_true(!strcmp(git_object_type2string(1234), ""));
END_TEST
BEGIN_TEST(objtype1, "convert string to type")
must_be_true(git_object_string2type(NULL) == GIT_OBJ_BAD);
must_be_true(git_object_string2type("") == GIT_OBJ_BAD);
must_be_true(git_object_string2type("commit") == GIT_OBJ_COMMIT);
must_be_true(git_object_string2type("tree") == GIT_OBJ_TREE);
must_be_true(git_object_string2type("blob") == GIT_OBJ_BLOB);
must_be_true(git_object_string2type("tag") == GIT_OBJ_TAG);
must_be_true(git_object_string2type("OFS_DELTA") == GIT_OBJ_OFS_DELTA);
must_be_true(git_object_string2type("REF_DELTA") == GIT_OBJ_REF_DELTA);
must_be_true(git_object_string2type("CoMmIt") == GIT_OBJ_BAD);
must_be_true(git_object_string2type("hohoho") == GIT_OBJ_BAD);
END_TEST
BEGIN_TEST(objtype2, "check if an object type is loose")
must_be_true(git_object_typeisloose(GIT_OBJ_BAD) == 0);
must_be_true(git_object_typeisloose(GIT_OBJ__EXT1) == 0);
must_be_true(git_object_typeisloose(GIT_OBJ_COMMIT) == 1);
must_be_true(git_object_typeisloose(GIT_OBJ_TREE) == 1);
must_be_true(git_object_typeisloose(GIT_OBJ_BLOB) == 1);
must_be_true(git_object_typeisloose(GIT_OBJ_TAG) == 1);
must_be_true(git_object_typeisloose(GIT_OBJ__EXT2) == 0);
must_be_true(git_object_typeisloose(GIT_OBJ_OFS_DELTA) == 0);
must_be_true(git_object_typeisloose(GIT_OBJ_REF_DELTA) == 0);
must_be_true(git_object_typeisloose(-2) == 0);
must_be_true(git_object_typeisloose(8) == 0);
must_be_true(git_object_typeisloose(1234) == 0);
END_TEST
BEGIN_TEST(objhash0, "hash junk data")
git_oid id, id_zero;
must_pass(git_oid_fromstr(&id_zero, zero_id));
/* invalid types: */
junk_obj.data = some_data;
must_fail(hash_object(&id, &junk_obj));
junk_obj.type = GIT_OBJ__EXT1;
must_fail(hash_object(&id, &junk_obj));
junk_obj.type = GIT_OBJ__EXT2;
must_fail(hash_object(&id, &junk_obj));
junk_obj.type = GIT_OBJ_OFS_DELTA;
must_fail(hash_object(&id, &junk_obj));
junk_obj.type = GIT_OBJ_REF_DELTA;
must_fail(hash_object(&id, &junk_obj));
/* data can be NULL only if len is zero: */
junk_obj.type = GIT_OBJ_BLOB;
junk_obj.data = NULL;
must_pass(hash_object(&id, &junk_obj));
must_be_true(git_oid_cmp(&id, &id_zero) == 0);
junk_obj.len = 1;
must_fail(hash_object(&id, &junk_obj));
END_TEST
BEGIN_TEST(objhash1, "hash a commit object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, commit_id));
must_pass(hash_object(&id2, &commit_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash2, "hash a tree object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, tree_id));
must_pass(hash_object(&id2, &tree_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash3, "hash a tag object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, tag_id));
must_pass(hash_object(&id2, &tag_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash4, "hash a zero-length object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, zero_id));
must_pass(hash_object(&id2, &zero_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash5, "hash an one-byte long object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, one_id));
must_pass(hash_object(&id2, &one_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash6, "hash a two-byte long object")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, two_id));
must_pass(hash_object(&id2, &two_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_TEST(objhash7, "hash an object several bytes long")
git_oid id1, id2;
must_pass(git_oid_fromstr(&id1, some_id));
must_pass(hash_object(&id2, &some_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
END_TEST
BEGIN_SUITE(rawobjects)
ADD_TEST(oid0);
ADD_TEST(oid1);
ADD_TEST(oid2);
ADD_TEST(oid3);
ADD_TEST(oid4);
ADD_TEST(oid5);
ADD_TEST(oid6);
ADD_TEST(oid7);
ADD_TEST(oid8);
ADD_TEST(oid9);
ADD_TEST(oid10);
ADD_TEST(oid11);
ADD_TEST(oid12);
ADD_TEST(oid13);
ADD_TEST(oid14);
ADD_TEST(oid15);
ADD_TEST(oid16);
ADD_TEST(oid17);
ADD_TEST(hash0);
ADD_TEST(hash1);
ADD_TEST(hash2);
ADD_TEST(objtype0);
ADD_TEST(objtype1);
ADD_TEST(objtype2);
ADD_TEST(objhash0);
ADD_TEST(objhash1);
ADD_TEST(objhash2);
ADD_TEST(objhash3);
ADD_TEST(objhash4);
ADD_TEST(objhash5);
ADD_TEST(objhash6);
ADD_TEST(objhash7);
END_SUITE
/*
* 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 "test_lib.h"
#include "fileops.h"
#include "odb.h"
static char *odb_dir = "test-objects";
#include "t03-data.h"
static int make_odb_dir(void)
{
if (p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
fprintf(stderr, " (already exists)");
fprintf(stderr, "\n");
return -1;
}
return 0;
}
static int check_object_files(object_data *d)
{
if (git_path_exists(d->dir) < 0)
return -1;
if (git_path_exists(d->file) < 0)
return -1;
return 0;
}
static int cmp_objects(git_rawobj *o1, git_rawobj *o2)
{
if (o1->type != o2->type)
return -1;
if (o1->len != o2->len)
return -1;
if ((o1->len > 0) && (memcmp(o1->data, o2->data, o1->len) != 0))
return -1;
return 0;
}
static int remove_object_files(object_data *d)
{
if (p_unlink(d->file) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", d->file);
return -1;
}
if ((p_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove directory \"%s\"\n", d->dir);
return -1;
}
if (p_rmdir(odb_dir) < 0) {
fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir);
return -1;
}
return 0;
}
static int streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw)
{
git_odb_stream *stream;
int error;
if ((error = git_odb_open_wstream(&stream, odb, raw->len, raw->type)) < GIT_SUCCESS)
return error;
stream->write(stream, raw->data, raw->len);
error = stream->finalize_write(oid, stream);
stream->free(stream);
return error;
}
BEGIN_TEST(write0, "write loose commit object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, commit.id));
must_pass(streaming_write(&id2, db, &commit_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&commit));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &commit_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&commit));
END_TEST
BEGIN_TEST(write1, "write loose tree object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, tree.id));
must_pass(streaming_write(&id2, db, &tree_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&tree));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &tree_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&tree));
END_TEST
BEGIN_TEST(write2, "write loose tag object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, tag.id));
must_pass(streaming_write(&id2, db, &tag_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&tag));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &tag_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&tag));
END_TEST
BEGIN_TEST(write3, "write zero-length object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, zero.id));
must_pass(streaming_write(&id2, db, &zero_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&zero));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &zero_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&zero));
END_TEST
BEGIN_TEST(write4, "write one-byte long object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, one.id));
must_pass(streaming_write(&id2, db, &one_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&one));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &one_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&one));
END_TEST
BEGIN_TEST(write5, "write two-byte long object")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, two.id));
must_pass(streaming_write(&id2, db, &two_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&two));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &two_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&two));
END_TEST
BEGIN_TEST(write6, "write an object which is several bytes long")
git_odb *db;
git_oid id1, id2;
git_odb_object *obj;
must_pass(make_odb_dir());
must_pass(git_odb_open(&db, odb_dir));
must_pass(git_oid_fromstr(&id1, some.id));
must_pass(streaming_write(&id2, db, &some_obj));
must_be_true(git_oid_cmp(&id1, &id2) == 0);
must_pass(check_object_files(&some));
must_pass(git_odb_read(&obj, db, &id1));
must_pass(cmp_objects(&obj->raw, &some_obj));
git_odb_object_free(obj);
git_odb_free(db);
must_pass(remove_object_files(&some));
END_TEST
BEGIN_SUITE(objwrite)
ADD_TEST(write0);
ADD_TEST(write1);
ADD_TEST(write2);
ADD_TEST(write3);
ADD_TEST(write4);
ADD_TEST(write5);
ADD_TEST(write6);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "commit.h"
#include "signature.h"
static char *test_commits_broken[] = {
/* empty commit */
"",
/* random garbage */
"asd97sa9du902e9a0jdsuusad09as9du098709aweu8987sd\n",
/* broken endlines 1 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\r\n\
parent 05452d6349abcd67aa396dfb28660d765d8b2a36\r\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\r\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\r\n\
\r\n\
a test commit with broken endlines\r\n",
/* broken endlines 2 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\
parent 05452d6349abcd67aa396dfb28660d765d8b2a36\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\
\
another test commit with broken endlines",
/* starting endlines */
"\ntree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\
parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
\n\
a test commit with a starting endline\n",
/* corrupted commit 1 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\
parent 05452d6349abcd67aa396df",
/* corrupted commit 2 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\
parent ",
/* corrupted commit 3 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\
parent ",
/* corrupted commit 4 */
"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\
par",
};
static char *test_commits_working[] = {
/* simple commit with no message */
"tree 1810dff58d8a660512d4832e740f692884338ccd\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
\n",
/* simple commit, no parent */
"tree 1810dff58d8a660512d4832e740f692884338ccd\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
\n\
a simple commit which works\n",
/* simple commit, no parent, no newline in message */
"tree 1810dff58d8a660512d4832e740f692884338ccd\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
\n\
a simple commit which works",
/* simple commit, 1 parent */
"tree 1810dff58d8a660512d4832e740f692884338ccd\n\
parent e90810b8df3e80c413d903f631643c716887138d\n\
author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
\n\
a simple commit which works\n",
};
BEGIN_TEST(parse0, "parse the OID line in a commit")
git_oid oid;
#define TEST_OID_PASS(string, header) { \
const char *ptr = string;\
const char *ptr_original = ptr;\
size_t len = strlen(ptr);\
must_pass(git_oid__parse(&oid, &ptr, ptr + len, header));\
must_be_true(ptr == ptr_original + len);\
}
#define TEST_OID_FAIL(string, header) { \
const char *ptr = string;\
size_t len = strlen(ptr);\
must_fail(git_oid__parse(&oid, &ptr, ptr + len, header));\
}
TEST_OID_PASS("parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "parent ");
TEST_OID_PASS("tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree ");
TEST_OID_PASS("random_heading 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "random_heading ");
TEST_OID_PASS("stuck_heading05452d6349abcd67aa396dfb28660d765d8b2a36\n", "stuck_heading");
TEST_OID_PASS("tree 5F4BEFFC0759261D015AA63A3A85613FF2F235DE\n", "tree ");
TEST_OID_PASS("tree 1A669B8AB81B5EB7D9DB69562D34952A38A9B504\n", "tree ");
TEST_OID_PASS("tree 5B20DCC6110FCC75D31C6CEDEBD7F43ECA65B503\n", "tree ");
TEST_OID_PASS("tree 173E7BF00EA5C33447E99E6C1255954A13026BE4\n", "tree ");
TEST_OID_FAIL("parent 05452d6349abcd67aa396dfb28660d765d8b2a36", "parent ");
TEST_OID_FAIL("05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree ");
TEST_OID_FAIL("parent05452d6349abcd67aa396dfb28660d765d8b2a6a\n", "parent ");
TEST_OID_FAIL("parent 05452d6349abcd67aa396dfb280d765d8b2a6\n", "parent ");
TEST_OID_FAIL("tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree ");
TEST_OID_FAIL("parent 0545xd6349abcd67aa396dfb28660d765d8b2a36\n", "parent ");
TEST_OID_FAIL("parent 0545xd6349abcd67aa396dfb28660d765d8b2a36FF\n", "parent ");
TEST_OID_FAIL("", "tree ");
TEST_OID_FAIL("", "");
#undef TEST_OID_PASS
#undef TEST_OID_FAIL
END_TEST
BEGIN_TEST(parse1, "parse the signature line in a commit")
#define TEST_SIGNATURE_PASS(_string, _header, _name, _email, _time, _offset) { \
const char *ptr = _string; \
size_t len = strlen(_string);\
git_signature person = {NULL, NULL, {0, 0}}; \
must_pass(git_signature__parse(&person, &ptr, ptr + len, _header, '\n'));\
must_be_true(strcmp(_name, person.name) == 0);\
must_be_true(strcmp(_email, person.email) == 0);\
must_be_true(_time == person.when.time);\
must_be_true(_offset == person.when.offset);\
git__free(person.name); git__free(person.email);\
}
#define TEST_SIGNATURE_FAIL(_string, _header) { \
const char *ptr = _string; \
size_t len = strlen(_string);\
git_signature person = {NULL, NULL, {0, 0}}; \
must_fail(git_signature__parse(&person, &ptr, ptr + len, _header, '\n'));\
git__free(person.name); git__free(person.email);\
}
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
12345,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <> 12345 \n",
"author ",
"Vicent Marti",
"",
12345,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com> 231301 +1020\n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
231301,
620);
TEST_SIGNATURE_PASS(
"author Vicent Marti with an outrageously long name \
which will probably overflow the buffer <tanoku@gmail.com> 12345 \n",
"author ",
"Vicent Marti with an outrageously long name \
which will probably overflow the buffer",
"tanoku@gmail.com",
12345,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanokuwithaveryveryverylongemail\
whichwillprobablyvoverflowtheemailbuffer@gmail.com> 12345 \n",
"author ",
"Vicent Marti",
"tanokuwithaveryveryverylongemail\
whichwillprobablyvoverflowtheemailbuffer@gmail.com",
12345,
0);
TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0000 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
0);
TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0100 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
60);
TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 -0100 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
-60);
/* Parse a signature without an author field */
TEST_SIGNATURE_PASS(
"committer <tanoku@gmail.com> 123456 -0100 \n",
"committer ",
"",
"tanoku@gmail.com",
123456,
-60);
/* Parse a signature without an author field */
TEST_SIGNATURE_PASS(
"committer <tanoku@gmail.com> 123456 -0100 \n",
"committer ",
"",
"tanoku@gmail.com",
123456,
-60);
/* Parse a signature with an empty author field */
TEST_SIGNATURE_PASS(
"committer <tanoku@gmail.com> 123456 -0100 \n",
"committer ",
"",
"tanoku@gmail.com",
123456,
-60);
/* Parse a signature with an empty email field */
TEST_SIGNATURE_PASS(
"committer Vicent Marti <> 123456 -0100 \n",
"committer ",
"Vicent Marti",
"",
123456,
-60);
/* Parse a signature with an empty email field */
TEST_SIGNATURE_PASS(
"committer Vicent Marti < > 123456 -0100 \n",
"committer ",
"Vicent Marti",
"",
123456,
-60);
/* Parse a signature with empty name and email */
TEST_SIGNATURE_PASS(
"committer <> 123456 -0100 \n",
"committer ",
"",
"",
123456,
-60);
/* Parse a signature with empty name and email */
TEST_SIGNATURE_PASS(
"committer <> 123456 -0100 \n",
"committer ",
"",
"",
123456,
-60);
/* Parse a signature with empty name and email */
TEST_SIGNATURE_PASS(
"committer < > 123456 -0100 \n",
"committer ",
"",
"",
123456,
-60);
/* Parse an obviously invalid signature */
TEST_SIGNATURE_PASS(
"committer foo<@bar> 123456 -0100 \n",
"committer ",
"foo",
"@bar",
123456,
-60);
/* Parse an obviously invalid signature */
TEST_SIGNATURE_PASS(
"committer foo<@bar>123456 -0100 \n",
"committer ",
"foo",
"@bar",
123456,
-60);
/* Parse an obviously invalid signature */
TEST_SIGNATURE_PASS(
"committer <>\n",
"committer ",
"",
"",
0,
0);
TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 -1500 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0163 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com> notime \n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com> 123456 notimezone \n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com> notime +0100\n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"author Vicent Marti <tanoku@gmail.com>\n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
0,
0);
TEST_SIGNATURE_PASS(
"author A U Thor <author@example.com>, C O. Miter <comiter@example.com> 1234567890 -0700\n",
"author ",
"A U Thor",
"author@example.com",
1234567890,
-420);
TEST_SIGNATURE_PASS(
"author A U Thor <author@example.com> and others 1234567890 -0700\n",
"author ",
"A U Thor",
"author@example.com",
1234567890,
-420);
TEST_SIGNATURE_PASS(
"author A U Thor <author@example.com> and others 1234567890\n",
"author ",
"A U Thor",
"author@example.com",
1234567890,
0);
TEST_SIGNATURE_PASS(
"author A U Thor> <author@example.com> and others 1234567890\n",
"author ",
"A U Thor>",
"author@example.com",
1234567890,
0);
TEST_SIGNATURE_FAIL(
"committer Vicent Marti tanoku@gmail.com> 123456 -0100 \n",
"committer ");
TEST_SIGNATURE_FAIL(
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
"author ");
TEST_SIGNATURE_FAIL(
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
"committer ");
TEST_SIGNATURE_FAIL(
"author Vicent Marti 12345 \n",
"author ");
TEST_SIGNATURE_FAIL(
"author Vicent Marti <broken@email 12345 \n",
"author ");
TEST_SIGNATURE_FAIL(
"committer Vicent Marti ><\n",
"committer ");
TEST_SIGNATURE_FAIL(
"author ",
"author ");
#undef TEST_SIGNATURE_PASS
#undef TEST_SIGNATURE_FAIL
END_TEST
static int try_build_signature(const char *name, const char *email, git_time_t time, int offset)
{
git_signature *sign;
int error = GIT_SUCCESS;
if ((error = git_signature_new(&sign, name, email, time, offset)) < GIT_SUCCESS)
return error;
git_signature_free((git_signature *)sign);
return error;
}
BEGIN_TEST(signature0, "creating a signature trims leading and trailing spaces")
git_signature *sign;
must_pass(git_signature_new(&sign, " nulltoken ", " emeric.fermas@gmail.com ", 1234567890, 60));
must_be_true(strcmp(sign->name, "nulltoken") == 0);
must_be_true(strcmp(sign->email, "emeric.fermas@gmail.com") == 0);
git_signature_free((git_signature *)sign);
END_TEST
BEGIN_TEST(signature1, "can not create a signature with empty name or email")
must_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60));
must_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60));
must_fail(try_build_signature(" ", "emeric.fermas@gmail.com", 1234567890, 60));
must_fail(try_build_signature("nulltoken", "", 1234567890, 60));
must_fail(try_build_signature("nulltoken", " ", 1234567890, 60));
END_TEST
BEGIN_TEST(signature2, "creating a one character signature")
git_signature *sign;
must_pass(git_signature_new(&sign, "x", "foo@bar.baz", 1234567890, 60));
must_be_true(strcmp(sign->name, "x") == 0);
must_be_true(strcmp(sign->email, "foo@bar.baz") == 0);
git_signature_free((git_signature *)sign);
END_TEST
BEGIN_TEST(signature3, "creating a two character signature")
git_signature *sign;
must_pass(git_signature_new(&sign, "xx", "x@y.z", 1234567890, 60));
must_be_true(strcmp(sign->name, "xx") == 0);
must_be_true(strcmp(sign->email, "x@y.z") == 0);
git_signature_free((git_signature *)sign);
END_TEST
BEGIN_TEST(signature4, "creating a zero character signature")
git_signature *sign;
must_fail(git_signature_new(&sign, "", "x@y.z", 1234567890, 60));
must_be_true(sign == NULL);
END_TEST
BEGIN_TEST(parse2, "parse a whole commit buffer")
const int broken_commit_count = sizeof(test_commits_broken) / sizeof(*test_commits_broken);
const int working_commit_count = sizeof(test_commits_working) / sizeof(*test_commits_working);
int i;
git_repository *repo;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
for (i = 0; i < broken_commit_count; ++i) {
git_commit *commit;
commit = git__malloc(sizeof(git_commit));
memset(commit, 0x0, sizeof(git_commit));
commit->object.repo = repo;
must_fail(git_commit__parse_buffer(
commit,
test_commits_broken[i],
strlen(test_commits_broken[i]))
);
git_commit__free(commit);
}
for (i = 0; i < working_commit_count; ++i) {
git_commit *commit;
commit = git__malloc(sizeof(git_commit));
memset(commit, 0x0, sizeof(git_commit));
commit->object.repo = repo;
must_pass(git_commit__parse_buffer(
commit,
test_commits_working[i],
strlen(test_commits_working[i]))
);
git_commit__free(commit);
commit = git__malloc(sizeof(git_commit));
memset(commit, 0x0, sizeof(git_commit));
commit->object.repo = repo;
must_pass(git_commit__parse_buffer(
commit,
test_commits_working[i],
strlen(test_commits_working[i]))
);
git_commit__free(commit);
}
git_repository_free(repo);
END_TEST
static const char *commit_ids[] = {
"a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */
"9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */
"c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */
"8496071c1b46c854b31185ea97743be6a8774479", /* 4 */
"5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */
};
BEGIN_TEST(details0, "query the details on a parsed commit")
const size_t commit_count = sizeof(commit_ids) / sizeof(const char *);
unsigned int i;
git_repository *repo;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
for (i = 0; i < commit_count; ++i) {
git_oid id;
git_commit *commit;
const git_signature *author, *committer;
const char *message;
git_time_t commit_time;
unsigned int parents, p;
git_commit *parent = NULL, *old_parent = NULL;
git_oid_fromstr(&id, commit_ids[i]);
must_pass(git_commit_lookup(&commit, repo, &id));
message = git_commit_message(commit);
author = git_commit_author(commit);
committer = git_commit_committer(commit);
commit_time = git_commit_time(commit);
parents = git_commit_parentcount(commit);
must_be_true(strcmp(author->name, "Scott Chacon") == 0);
must_be_true(strcmp(author->email, "schacon@gmail.com") == 0);
must_be_true(strcmp(committer->name, "Scott Chacon") == 0);
must_be_true(strcmp(committer->email, "schacon@gmail.com") == 0);
must_be_true(message != NULL);
must_be_true(strchr(message, '\n') != NULL);
must_be_true(commit_time > 0);
must_be_true(parents <= 2);
for (p = 0;p < parents;p++) {
if (old_parent != NULL)
git_commit_free(old_parent);
old_parent = parent;
must_pass(git_commit_parent(&parent, commit, p));
must_be_true(parent != NULL);
must_be_true(git_commit_author(parent) != NULL); // is it really a commit?
}
git_commit_free(old_parent);
git_commit_free(parent);
must_fail(git_commit_parent(&parent, commit, parents));
git_commit_free(commit);
}
git_repository_free(repo);
END_TEST
#define COMMITTER_NAME "Vicent Marti"
#define COMMITTER_EMAIL "vicent@github.com"
#define COMMIT_MESSAGE "This commit has been created in memory\n\
This is a commit created in memory and it will be written back to disk\n"
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
BEGIN_TEST(write0, "write a new commit object from memory to disk")
git_repository *repo;
git_commit *commit;
git_oid tree_id, parent_id, commit_id;
git_signature *author, *committer;
const git_signature *author1, *committer1;
git_commit *parent;
git_tree *tree;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&tree_id, tree_oid);
must_pass(git_tree_lookup(&tree, repo, &tree_id));
git_oid_fromstr(&parent_id, commit_ids[4]);
must_pass(git_commit_lookup(&parent, repo, &parent_id));
/* create signatures */
must_pass(git_signature_new(&committer, COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60));
must_pass(git_signature_new(&author, COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90));
must_pass(git_commit_create_v(
&commit_id, /* out id */
repo,
NULL, /* do not update the HEAD */
author,
committer,
NULL,
COMMIT_MESSAGE,
tree,
1, parent));
git_object_free((git_object *)parent);
git_object_free((git_object *)tree);
git_signature_free(committer);
git_signature_free(author);
must_pass(git_commit_lookup(&commit, repo, &commit_id));
/* Check attributes were set correctly */
author1 = git_commit_author(commit);
must_be_true(author1 != NULL);
must_be_true(strcmp(author1->name, COMMITTER_NAME) == 0);
must_be_true(strcmp(author1->email, COMMITTER_EMAIL) == 0);
must_be_true(author1->when.time == 987654321);
must_be_true(author1->when.offset == 90);
committer1 = git_commit_committer(commit);
must_be_true(committer1 != NULL);
must_be_true(strcmp(committer1->name, COMMITTER_NAME) == 0);
must_be_true(strcmp(committer1->email, COMMITTER_EMAIL) == 0);
must_be_true(committer1->when.time == 123456789);
must_be_true(committer1->when.offset == 60);
must_be_true(strcmp(git_commit_message(commit), COMMIT_MESSAGE) == 0);
#ifndef GIT_WIN32
must_be_true((loose_object_mode(REPOSITORY_FOLDER, (git_object *)commit) & 0777) == GIT_OBJECT_FILE_MODE);
#endif
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
git_commit_free(commit);
git_repository_free(repo);
END_TEST
#define ROOT_COMMIT_MESSAGE "This is a root commit\n\
This is a root commit and should be the only one in this branch\n"
BEGIN_TEST(root0, "create a root commit")
git_repository *repo;
git_commit *commit;
git_oid tree_id, commit_id;
const git_oid *branch_oid;
git_signature *author, *committer;
const char *branch_name = "refs/heads/root-commit-branch";
git_reference *head, *branch;
char *head_old;
git_tree *tree;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&tree_id, tree_oid);
must_pass(git_tree_lookup(&tree, repo, &tree_id));
/* create signatures */
must_pass(git_signature_new(&committer, COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60));
must_pass(git_signature_new(&author, COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90));
/* First we need to update HEAD so it points to our non-existant branch */
must_pass(git_reference_lookup(&head, repo, "HEAD"));
must_be_true(git_reference_type(head) == GIT_REF_SYMBOLIC);
head_old = git__strdup(git_reference_target(head));
must_be_true(head_old != NULL);
must_pass(git_reference_set_target(head, branch_name));
must_pass(git_commit_create_v(
&commit_id, /* out id */
repo,
"HEAD",
author,
committer,
NULL,
ROOT_COMMIT_MESSAGE,
tree,
0));
git_object_free((git_object *)tree);
git_signature_free(committer);
git_signature_free(author);
/*
* The fact that creating a commit works has already been
* tested. Here we just make sure it's our commit and that it was
* written as a root commit.
*/
must_pass(git_commit_lookup(&commit, repo, &commit_id));
must_be_true(git_commit_parentcount(commit) == 0);
must_pass(git_reference_lookup(&branch, repo, branch_name));
branch_oid = git_reference_oid(branch);
must_pass(git_oid_cmp(branch_oid, &commit_id));
must_be_true(!strcmp(git_commit_message(commit), ROOT_COMMIT_MESSAGE));
/* Remove the data we just added to the repo */
git_reference_free(head);
must_pass(git_reference_lookup(&head, repo, "HEAD"));
must_pass(git_reference_set_target(head, head_old));
must_pass(git_reference_delete(branch));
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
git__free(head_old);
git_commit_free(commit);
git_repository_free(repo);
git_reference_free(head);
END_TEST
BEGIN_SUITE(commit)
ADD_TEST(parse0);
ADD_TEST(parse1);
ADD_TEST(parse2);
ADD_TEST(details0);
ADD_TEST(write0);
ADD_TEST(root0);
ADD_TEST(signature0);
ADD_TEST(signature1);
ADD_TEST(signature2);
ADD_TEST(signature3);
ADD_TEST(signature4);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
/*
$ git log --oneline --graph --decorate
* a4a7dce (HEAD, br2) Merge branch 'master' into br2
|\
| * 9fd738e (master) a fourth commit
| * 4a202b3 a third commit
* | c47800c branch commit one
|/
* 5b5b025 another commit
* 8496071 testing
*/
static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f";
static const char *commit_ids[] = {
"a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */
"9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */
"c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */
"8496071c1b46c854b31185ea97743be6a8774479", /* 4 */
"5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */
};
/* Careful: there are two possible topological sorts */
static const int commit_sorting_topo[][6] = {
{0, 1, 2, 3, 5, 4}, {0, 3, 1, 2, 5, 4}
};
static const int commit_sorting_time[][6] = {
{0, 3, 1, 2, 5, 4}
};
static const int commit_sorting_topo_reverse[][6] = {
{4, 5, 3, 2, 1, 0}, {4, 5, 2, 1, 3, 0}
};
static const int commit_sorting_time_reverse[][6] = {
{4, 5, 2, 1, 3, 0}
};
#define commit_count 6
static const int result_bytes = 24;
static int get_commit_index(git_oid *raw_oid)
{
int i;
char oid[40];
git_oid_fmt(oid, raw_oid);
for (i = 0; i < commit_count; ++i)
if (memcmp(oid, commit_ids[i], 40) == 0)
return i;
return -1;
}
static int test_walk(git_revwalk *walk, const git_oid *root,
int flags, const int possible_results[][6], int results_count)
{
git_oid oid;
int i;
int result_array[commit_count];
git_revwalk_sorting(walk, flags);
git_revwalk_push(walk, root);
for (i = 0; i < commit_count; ++i)
result_array[i] = -1;
i = 0;
while (git_revwalk_next(&oid, walk) == GIT_SUCCESS) {
result_array[i++] = get_commit_index(&oid);
/*{
char str[41];
git_oid_fmt(str, &oid);
str[40] = 0;
printf(" %d) %s\n", i, str);
}*/
}
for (i = 0; i < results_count; ++i)
if (memcmp(possible_results[i],
result_array, result_bytes) == 0)
return GIT_SUCCESS;
return GIT_ERROR;
}
BEGIN_TEST(walk0, "do a simple walk on a repo with different sorting modes")
git_oid id;
git_repository *repo;
git_revwalk *walk;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_revwalk_new(&walk, repo));
git_oid_fromstr(&id, commit_head);
must_pass(test_walk(walk, &id, GIT_SORT_TIME, commit_sorting_time, 1));
must_pass(test_walk(walk, &id, GIT_SORT_TOPOLOGICAL, commit_sorting_topo, 2));
must_pass(test_walk(walk, &id, GIT_SORT_TIME | GIT_SORT_REVERSE, commit_sorting_time_reverse, 1));
must_pass(test_walk(walk, &id, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE, commit_sorting_topo_reverse, 2));
git_revwalk_free(walk);
git_repository_free(repo);
END_TEST
BEGIN_SUITE(revwalk)
ADD_TEST(walk0);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "index.h"
#define TEST_INDEX_ENTRY_COUNT 109
#define TEST_INDEX2_ENTRY_COUNT 1437
struct test_entry {
unsigned int index;
char path[128];
git_off_t file_size;
git_time_t mtime;
};
struct test_entry TEST_ENTRIES[] = {
{4, "Makefile", 5064, 0x4C3F7F33},
{62, "tests/Makefile", 2631, 0x4C3F7F33},
{36, "src/index.c", 10014, 0x4C43368D},
{6, "git.git-authors", 2709, 0x4C3F7F33},
{48, "src/revobject.h", 1448, 0x4C3F7FE2}
};
BEGIN_TEST(read0, "load an empty index")
git_index *index;
must_pass(git_index_open(&index, "in-memory-index"));
must_be_true(index->on_disk == 0);
must_be_true(git_index_entrycount(index) == 0);
must_be_true(index->entries.sorted);
git_index_free(index);
END_TEST
BEGIN_TEST(read1, "load a standard index (default test index)")
git_index *index;
unsigned int i;
git_index_entry **entries;
must_pass(git_index_open(&index, TEST_INDEX_PATH));
must_be_true(index->on_disk);
must_be_true(git_index_entrycount(index) == TEST_INDEX_ENTRY_COUNT);
must_be_true(index->entries.sorted);
entries = (git_index_entry **)index->entries.contents;
for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
git_index_entry *e = entries[TEST_ENTRIES[i].index];
must_be_true(strcmp(e->path, TEST_ENTRIES[i].path) == 0);
must_be_true(e->mtime.seconds == TEST_ENTRIES[i].mtime);
must_be_true(e->file_size == TEST_ENTRIES[i].file_size);
}
git_index_free(index);
END_TEST
BEGIN_TEST(read2, "load a standard index (git.git index)")
git_index *index;
must_pass(git_index_open(&index, TEST_INDEX2_PATH));
must_be_true(index->on_disk);
must_be_true(git_index_entrycount(index) == TEST_INDEX2_ENTRY_COUNT);
must_be_true(index->entries.sorted);
must_be_true(index->tree != NULL);
git_index_free(index);
END_TEST
BEGIN_TEST(find0, "find an entry on an index")
git_index *index;
unsigned int i;
must_pass(git_index_open(&index, TEST_INDEX_PATH));
for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
int idx = git_index_find(index, TEST_ENTRIES[i].path);
must_be_true((unsigned int)idx == TEST_ENTRIES[i].index);
}
git_index_free(index);
END_TEST
BEGIN_TEST(find1, "find an entry in an empty index")
git_index *index;
unsigned int i;
must_pass(git_index_open(&index, "fake-index"));
for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
int idx = git_index_find(index, TEST_ENTRIES[i].path);
must_be_true(idx == GIT_ENOTFOUND);
}
git_index_free(index);
END_TEST
BEGIN_TEST(write0, "write an index back to disk")
git_index *index;
must_pass(copy_file(TEST_INDEXBIG_PATH, "index_rewrite"));
must_pass(git_index_open(&index, "index_rewrite"));
must_be_true(index->on_disk);
must_pass(git_index_write(index));
must_pass(cmp_files(TEST_INDEXBIG_PATH, "index_rewrite"));
git_index_free(index);
p_unlink("index_rewrite");
END_TEST
BEGIN_TEST(sort0, "sort the entires in an index")
/*
* TODO: This no longer applies:
* index sorting in Git uses some specific changes to the way
* directories are sorted.
*
* We need to specificially check for this by creating a new
* index, adding entries in random order and then
* checking for consistency
*/
END_TEST
BEGIN_TEST(sort1, "sort the entires in an empty index")
git_index *index;
must_pass(git_index_open(&index, "fake-index"));
/* FIXME: this test is slightly dumb */
must_be_true(index->entries.sorted);
git_index_free(index);
END_TEST
BEGIN_TEST(add0, "add a new file to the index")
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
git_repository *repo;
git_index_entry *entry;
git_oid id1;
/* Intialize a new repository */
must_pass(git_repository_init(&repo, TEMP_REPO_FOLDER "myrepo", 0));
/* Ensure we're the only guy in the room */
must_pass(git_repository_index(&index, repo));
must_pass(git_index_entrycount(index) == 0);
/* Create a new file in the working directory */
must_pass(git_futils_mkpath2file(TEMP_REPO_FOLDER "myrepo/test.txt", 0777));
must_pass(git_filebuf_open(&file, TEMP_REPO_FOLDER "myrepo/test.txt", 0));
must_pass(git_filebuf_write(&file, "hey there\n", 10));
must_pass(git_filebuf_commit(&file, 0666));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ echo "hey there" | git hash-object --stdin
*/
must_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
/* Add the new file to the index */
must_pass(git_index_add(index, "test.txt", 0));
/* Wow... it worked! */
must_pass(git_index_entrycount(index) == 1);
entry = git_index_get(index, 0);
/* And the built-in hashing mechanism worked as expected */
must_be_true(git_oid_cmp(&id1, &entry->oid) == 0);
git_index_free(index);
git_repository_free(repo);
must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
END_TEST
BEGIN_SUITE(index)
ADD_TEST(read0);
ADD_TEST(read1);
ADD_TEST(read2);
ADD_TEST(find0);
ADD_TEST(find1);
ADD_TEST(write0);
ADD_TEST(sort0);
ADD_TEST(sort1);
ADD_TEST(add0);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "tag.h"
static const char *tag1_id = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1";
static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980";
static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755";
static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
BEGIN_TEST(read0, "read and parse a tag from the repository")
git_repository *repo;
git_tag *tag1, *tag2;
git_commit *commit;
git_oid id1, id2, id_commit;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&id1, tag1_id);
git_oid_fromstr(&id2, tag2_id);
git_oid_fromstr(&id_commit, tagged_commit);
must_pass(git_tag_lookup(&tag1, repo, &id1));
must_be_true(strcmp(git_tag_name(tag1), "test") == 0);
must_be_true(git_tag_type(tag1) == GIT_OBJ_TAG);
must_pass(git_tag_target((git_object **)&tag2, tag1));
must_be_true(tag2 != NULL);
must_be_true(git_oid_cmp(&id2, git_tag_id(tag2)) == 0);
must_pass(git_tag_target((git_object **)&commit, tag2));
must_be_true(commit != NULL);
must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
git_tag_free(tag1);
git_tag_free(tag2);
git_commit_free(commit);
git_repository_free(repo);
END_TEST
BEGIN_TEST(read1, "list all tag names from the repository")
git_repository *repo;
git_strarray tag_list;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_tag_list(&tag_list, repo));
must_be_true(tag_list.count == 3);
git_strarray_free(&tag_list);
git_repository_free(repo);
END_TEST
static int ensure_tag_pattern_match(git_repository *repo, const char *pattern, const size_t expected_matches)
{
git_strarray tag_list;
int error = GIT_SUCCESS;
if ((error = git_tag_list_match(&tag_list, pattern, repo)) < GIT_SUCCESS)
goto exit;
if (tag_list.count != expected_matches)
error = GIT_ERROR;
exit:
git_strarray_free(&tag_list);
return error;
}
BEGIN_TEST(read2, "list all tag names from the repository matching a specified pattern")
git_repository *repo;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(ensure_tag_pattern_match(repo, "", 3));
must_pass(ensure_tag_pattern_match(repo, "*", 3));
must_pass(ensure_tag_pattern_match(repo, "t*", 1));
must_pass(ensure_tag_pattern_match(repo, "*b", 2));
must_pass(ensure_tag_pattern_match(repo, "e", 0));
must_pass(ensure_tag_pattern_match(repo, "e90810b", 1));
must_pass(ensure_tag_pattern_match(repo, "e90810[ab]", 1));
git_repository_free(repo);
END_TEST
#define BAD_TAG_REPOSITORY_FOLDER TEST_RESOURCES "/bad_tag.git/"
BEGIN_TEST(read3, "read and parse a tag without a tagger field")
git_repository *repo;
git_tag *bad_tag;
git_commit *commit;
git_oid id, id_commit;
must_pass(git_repository_open(&repo, BAD_TAG_REPOSITORY_FOLDER));
git_oid_fromstr(&id, bad_tag_id);
git_oid_fromstr(&id_commit, badly_tagged_commit);
must_pass(git_tag_lookup(&bad_tag, repo, &id));
must_be_true(bad_tag != NULL);
must_be_true(strcmp(git_tag_name(bad_tag), "e90810b") == 0);
must_be_true(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0);
must_be_true(bad_tag->tagger == NULL);
must_pass(git_tag_target((git_object **)&commit, bad_tag));
must_be_true(commit != NULL);
must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
git_tag_free(bad_tag);
git_commit_free(commit);
git_repository_free(repo);
END_TEST
#define TAGGER_NAME "Vicent Marti"
#define TAGGER_EMAIL "vicent@github.com"
#define TAGGER_MESSAGE "This is my tag.\n\nThere are many tags, but this one is mine\n"
BEGIN_TEST(write0, "write a tag to the repository and read it again")
git_repository *repo;
git_tag *tag;
git_oid target_id, tag_id;
git_signature *tagger;
const git_signature *tagger1;
git_reference *ref_tag;
git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
must_pass(git_signature_new(&tagger, TAGGER_NAME, TAGGER_EMAIL, 123456789, 60));
must_pass(git_tag_create(
&tag_id, /* out id */
repo,
"the-tag",
target,
tagger,
TAGGER_MESSAGE,
0));
git_object_free(target);
git_signature_free(tagger);
must_pass(git_tag_lookup(&tag, repo, &tag_id));
must_be_true(git_oid_cmp(git_tag_target_oid(tag), &target_id) == 0);
/* Check attributes were set correctly */
tagger1 = git_tag_tagger(tag);
must_be_true(tagger1 != NULL);
must_be_true(strcmp(tagger1->name, TAGGER_NAME) == 0);
must_be_true(strcmp(tagger1->email, TAGGER_EMAIL) == 0);
must_be_true(tagger1->when.time == 123456789);
must_be_true(tagger1->when.offset == 60);
must_be_true(strcmp(git_tag_message(tag), TAGGER_MESSAGE) == 0);
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/the-tag"));
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
must_pass(git_reference_delete(ref_tag));
#ifndef GIT_WIN32
must_be_true((loose_object_mode(REPOSITORY_FOLDER, (git_object *)tag) & 0777) == GIT_OBJECT_FILE_MODE);
#endif
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
git_tag_free(tag);
git_repository_free(repo);
END_TEST
BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag")
git_repository *repo;
git_oid target_id, tag_id;
git_signature *tagger;
git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
must_pass(git_signature_new(&tagger, TAGGER_NAME, TAGGER_EMAIL, 123456789, 60));
must_fail(git_tag_create(
&tag_id, /* out id */
repo,
"e90810b",
target,
tagger,
TAGGER_MESSAGE,
0));
git_object_free(target);
git_signature_free(tagger);
git_repository_free(repo);
END_TEST
BEGIN_TEST(write3, "Replace an already existing tag")
git_repository *repo;
git_oid target_id, tag_id, old_tag_id;
git_signature *tagger;
git_reference *ref_tag;
git_object *target;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
git_reference_free(ref_tag);
/* create signature */
must_pass(git_signature_new(&tagger, TAGGER_NAME, TAGGER_EMAIL, 123456789, 60));
must_pass(git_tag_create(
&tag_id, /* out id */
repo,
"e90810b",
target,
tagger,
TAGGER_MESSAGE,
1));
git_object_free(target);
git_signature_free(tagger);
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &old_tag_id) != 0);
close_temp_repo(repo);
git_reference_free(ref_tag);
END_TEST
BEGIN_TEST(write4, "write a lightweight tag to the repository and read it again")
git_repository *repo;
git_oid target_id, object_id;
git_reference *ref_tag;
git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
must_pass(git_tag_create_lightweight(
&object_id,
repo,
"light-tag",
target,
0));
git_object_free(target);
must_be_true(git_oid_cmp(&object_id, &target_id) == 0);
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/light-tag"));
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &target_id) == 0);
must_pass(git_tag_delete(repo, "light-tag"));
git_repository_free(repo);
git_reference_free(ref_tag);
END_TEST
BEGIN_TEST(write5, "Attempt to write a lightweight tag bearing the same name than an already existing tag")
git_repository *repo;
git_oid target_id, object_id, existing_object_id;
git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
must_fail(git_tag_create_lightweight(
&object_id,
repo,
"e90810b",
target,
0));
git_oid_fromstr(&existing_object_id, tag2_id);
must_be_true(git_oid_cmp(&object_id, &existing_object_id) == 0);
git_object_free(target);
git_repository_free(repo);
END_TEST
BEGIN_TEST(delete0, "Delete an already existing tag")
git_repository *repo;
git_reference *ref_tag;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_tag_delete(repo, "e90810b"));
must_fail(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
close_temp_repo(repo);
git_reference_free(ref_tag);
END_TEST
BEGIN_SUITE(tag)
ADD_TEST(read0);
ADD_TEST(read1);
ADD_TEST(read2);
ADD_TEST(read3);
ADD_TEST(write0);
ADD_TEST(write2);
ADD_TEST(write3);
ADD_TEST(write4);
ADD_TEST(write5);
ADD_TEST(delete0);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "tree.h"
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
static const char *blob_oid = "fa49b077972391ad58037050f2a75f74e3671e92";
static const char *first_tree = "181037049a54a1eb5fab404658a3a250b44335d7";
static const char *second_tree = "f60079018b664e4e79329a7ef9559c8d9e0378d1";
static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488";
#if 0
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
{
static const char *indent = " ";
git_tree *tree;
unsigned int i;
if (git_tree_lookup(&tree, repo, tree_oid) < GIT_SUCCESS)
return GIT_ERROR;
for (i = 0; i < git_tree_entrycount(tree); ++i) {
const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
char entry_oid[40];
git_oid_fmt(entry_oid, &entry->oid);
printf("%.*s%o [%.*s] %s\n", depth*2, indent, entry->attr, 40, entry_oid, entry->filename);
if (entry->attr == S_IFDIR) {
if (print_tree(repo, &entry->oid, depth + 1) < GIT_SUCCESS) {
git_tree_free(tree);
return GIT_ERROR;
}
}
}
git_tree_free(tree);
return GIT_SUCCESS;
}
#endif
BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
git_oid id;
git_repository *repo;
git_tree *tree;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&id, tree_oid);
must_pass(git_tree_lookup(&tree, repo, &id));
must_be_true(git_tree_entry_byname(tree, "README") != NULL);
must_be_true(git_tree_entry_byname(tree, "NOTEXISTS") == NULL);
must_be_true(git_tree_entry_byname(tree, "") == NULL);
must_be_true(git_tree_entry_byindex(tree, 0) != NULL);
must_be_true(git_tree_entry_byindex(tree, 2) != NULL);
must_be_true(git_tree_entry_byindex(tree, 3) == NULL);
must_be_true(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL);
git_tree_free(tree);
git_repository_free(repo);
END_TEST
BEGIN_TEST(read1, "read a tree from the repository")
git_oid id;
git_repository *repo;
git_tree *tree;
const git_tree_entry *entry;
git_object *obj;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&id, tree_oid);
must_pass(git_tree_lookup(&tree, repo, &id));
must_be_true(git_tree_entrycount(tree) == 3);
/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_TREE) == 0);
must_be_true(obj != NULL);
git_object_free(obj);
obj = NULL;
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_BLOB) == GIT_EINVALIDTYPE);
must_be_true(obj == NULL);
entry = git_tree_entry_byname(tree, "README");
must_be_true(entry != NULL);
must_be_true(strcmp(git_tree_entry_name(entry), "README") == 0);
must_pass(git_tree_entry_2object(&obj, repo, entry));
must_be_true(obj != NULL);
git_object_free(obj);
git_tree_free(tree);
git_repository_free(repo);
END_TEST
#if 0
BEGIN_TEST(write0, "write a tree from an index")
git_repository *repo;
git_index *index;
git_oid tree_oid;
must_pass(git_repository_open(&repo, "/tmp/redtmp/.git"));
must_pass(git_repository_index(&index, repo));
must_pass(git_tree_create_fromindex(&tree_oid, index));
must_pass(print_tree(repo, &tree_oid, 0));
git_repository_free(repo);
END_TEST
#endif
BEGIN_TEST(write2, "write a tree from a memory")
git_repository *repo;
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, rid, id2;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&id, first_tree);
git_oid_fromstr(&id2, second_tree);
git_oid_fromstr(&bid, blob_oid);
//create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER.
must_pass(git_tree_lookup(&tree, repo, &id));
must_pass(git_treebuilder_create(&builder, tree));
must_fail(git_treebuilder_insert(NULL, builder, "", &bid, 0100644));
must_fail(git_treebuilder_insert(NULL, builder, "/", &bid, 0100644));
must_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", &bid, 0100644));
must_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
must_pass(git_treebuilder_write(&rid,repo,builder));
must_be_true(git_oid_cmp(&rid, &id2) == 0);
git_treebuilder_free(builder);
git_tree_free(tree);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(write3, "write a hierarchical tree from a memory")
git_repository *repo;
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, subtree_id, id2, id3;
git_oid id_hiearar;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&id, first_tree);
git_oid_fromstr(&id2, second_tree);
git_oid_fromstr(&id3, third_tree);
git_oid_fromstr(&bid, blob_oid);
//create subtree
must_pass(git_treebuilder_create(&builder, NULL));
must_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
must_pass(git_treebuilder_write(&subtree_id,repo,builder));
git_treebuilder_free(builder);
// create parent tree
must_pass(git_tree_lookup(&tree, repo, &id));
must_pass(git_treebuilder_create(&builder, tree));
must_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000));
must_pass(git_treebuilder_write(&id_hiearar,repo,builder));
git_treebuilder_free(builder);
git_tree_free(tree);
must_be_true(git_oid_cmp(&id_hiearar, &id3) == 0);
// check data is correct
must_pass(git_tree_lookup(&tree, repo, &id_hiearar));
must_be_true(2 == git_tree_entrycount(tree));
#ifndef GIT_WIN32
must_be_true((loose_object_dir_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_DIR_MODE);
must_be_true((loose_object_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_FILE_MODE);
#endif
git_tree_free(tree);
close_temp_repo(repo);
END_TEST
BEGIN_SUITE(tree)
//ADD_TEST(print0);
ADD_TEST(read0);
ADD_TEST(read1);
//ADD_TEST(write0);
//ADD_TEST(write1);
ADD_TEST(write2);
ADD_TEST(write3);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "repository.h"
#include "git2/reflog.h"
#include "reflog.h"
static const char *loose_tag_ref_name = "refs/tags/e90810b";
static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist";
BEGIN_TEST(readtag0, "lookup a loose tag reference")
git_repository *repo;
git_reference *reference;
git_object *object;
git_buf ref_name_from_tag_name = GIT_BUF_INIT;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
must_be_true(git_reference_type(reference) & GIT_REF_OID);
must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
must_pass(git_object_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
must_be_true(object != NULL);
must_be_true(git_object_type(object) == GIT_OBJ_TAG);
/* Ensure the name of the tag matches the name of the reference */
must_pass(git_buf_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object)));
must_be_true(strcmp(ref_name_from_tag_name.ptr, loose_tag_ref_name) == 0);
git_buf_free(&ref_name_from_tag_name);
git_object_free(object);
git_repository_free(repo);
git_reference_free(reference);
END_TEST
BEGIN_TEST(readtag1, "lookup a loose tag reference that doesn't exist")
git_repository *repo;
git_reference *reference;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_fail(git_reference_lookup(&reference, repo, non_existing_tag_ref_name));
git_repository_free(repo);
git_reference_free(reference);
END_TEST
static const char *head_tracker_sym_ref_name = "head-tracker";
static const char *current_head_target = "refs/heads/master";
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
BEGIN_TEST(readsym0, "lookup a symbolic reference")
git_repository *repo;
git_reference *reference, *resolved_ref;
git_object *object;
git_oid id;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, GIT_HEAD_FILE));
must_be_true(git_reference_type(reference) & GIT_REF_SYMBOLIC);
must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, GIT_HEAD_FILE) == 0);
must_pass(git_reference_resolve(&resolved_ref, reference));
must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
must_pass(git_object_lookup(&object, repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
must_be_true(object != NULL);
must_be_true(git_object_type(object) == GIT_OBJ_COMMIT);
git_oid_fromstr(&id, current_master_tip);
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_free(object);
git_repository_free(repo);
git_reference_free(reference);
git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
git_repository *repo;
git_reference *reference, *resolved_ref;
git_object *object;
git_oid id;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, head_tracker_sym_ref_name));
must_be_true(git_reference_type(reference) & GIT_REF_SYMBOLIC);
must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, head_tracker_sym_ref_name) == 0);
must_pass(git_reference_resolve(&resolved_ref, reference));
must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
must_pass(git_object_lookup(&object, repo, git_reference_oid(resolved_ref), GIT_OBJ_ANY));
must_be_true(object != NULL);
must_be_true(git_object_type(object) == GIT_OBJ_COMMIT);
git_oid_fromstr(&id, current_master_tip);
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
git_object_free(object);
git_repository_free(repo);
git_reference_free(reference);
git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(readsym2, "lookup the HEAD and resolve the master branch")
git_repository *repo;
git_reference *reference, *resolved_ref, *comp_base_ref;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, head_tracker_sym_ref_name));
must_pass(git_reference_resolve(&comp_base_ref, reference));
git_reference_free(reference);
must_pass(git_reference_lookup(&reference, repo, GIT_HEAD_FILE));
must_pass(git_reference_resolve(&resolved_ref, reference));
must_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
git_reference_free(reference);
git_reference_free(resolved_ref);
must_pass(git_reference_lookup(&reference, repo, current_head_target));
must_pass(git_reference_resolve(&resolved_ref, reference));
must_pass(git_oid_cmp(git_reference_oid(comp_base_ref), git_reference_oid(resolved_ref)));
git_reference_free(reference);
git_reference_free(resolved_ref);
git_reference_free(comp_base_ref);
git_repository_free(repo);
END_TEST
BEGIN_TEST(readsym3, "lookup the master branch and then the HEAD")
git_repository *repo;
git_reference *reference, *master_ref, *resolved_ref;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&master_ref, repo, current_head_target));
must_pass(git_reference_lookup(&reference, repo, GIT_HEAD_FILE));
must_pass(git_reference_resolve(&resolved_ref, reference));
must_pass(git_oid_cmp(git_reference_oid(master_ref), git_reference_oid(resolved_ref)));
git_repository_free(repo);
git_reference_free(reference);
git_reference_free(resolved_ref);
git_reference_free(master_ref);
END_TEST
static const char *packed_head_name = "refs/heads/packed";
static const char *packed_test_head_name = "refs/heads/packed-test";
BEGIN_TEST(readpacked0, "lookup a packed reference")
git_repository *repo;
git_reference *reference;
git_object *object;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, packed_head_name));
must_be_true(git_reference_type(reference) & GIT_REF_OID);
must_be_true(git_reference_is_packed(reference));
must_be_true(strcmp(reference->name, packed_head_name) == 0);
must_pass(git_object_lookup(&object, repo, git_reference_oid(reference), GIT_OBJ_ANY));
must_be_true(object != NULL);
must_be_true(git_object_type(object) == GIT_OBJ_COMMIT);
git_object_free(object);
git_repository_free(repo);
git_reference_free(reference);
END_TEST
BEGIN_TEST(readpacked1, "assure that a loose reference is looked up before a packed reference")
git_repository *repo;
git_reference *reference;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&reference, repo, packed_head_name));
git_reference_free(reference);
must_pass(git_reference_lookup(&reference, repo, packed_test_head_name));
must_be_true(git_reference_type(reference) & GIT_REF_OID);
must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, packed_test_head_name) == 0);
git_repository_free(repo);
git_reference_free(reference);
END_TEST
BEGIN_TEST(create0, "create a new symbolic reference")
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo, *repo2;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "another-head-tracker";
git_oid_fromstr(&id, current_master_tip);
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
must_pass(git_buf_joinpath(&ref_path, repo->path_repository, new_head_tracker));
git_buf_free(&ref_path);
/* Create and write the new symbolic reference */
must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target, 0));
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
must_be_true(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC);
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
must_be_true(strcmp(looked_up_ref->name, new_head_tracker) == 0);
/* ...peeled.. */
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_reference_type(resolved_ref) == GIT_REF_OID);
/* ...and that it points to the current master tip */
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
git_repository_free(repo);
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
must_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker));
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
close_temp_repo(repo2);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
END_TEST
BEGIN_TEST(create1, "create a deep symbolic reference")
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "deep/rooted/tracker";
git_oid_fromstr(&id, current_master_tip);
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_buf_joinpath(&ref_path, repo->path_repository, new_head_tracker));
must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target, 0));
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
close_temp_repo(repo);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
git_buf_free(&ref_path);
END_TEST
BEGIN_TEST(create2, "create a new OID reference")
git_reference *new_reference, *looked_up_ref;
git_repository *repo, *repo2;
git_oid id;
git_buf ref_path = GIT_BUF_INIT;
const char *new_head = "refs/heads/new-head";
git_oid_fromstr(&id, current_master_tip);
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
must_pass(git_buf_joinpath(&ref_path, repo->path_repository, new_head));
/* Create and write the new object id reference */
must_pass(git_reference_create_oid(&new_reference, repo, new_head, &id, 0));
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
must_be_true(git_reference_type(looked_up_ref) & GIT_REF_OID);
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
must_be_true(strcmp(looked_up_ref->name, new_head) == 0);
/* ...and that it points to the current master tip */
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
git_reference_free(looked_up_ref);
git_repository_free(repo);
/* Similar test with a fresh new repository */
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
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);
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_buf_free(&ref_path);
END_TEST
BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unknown id")
git_reference *new_reference, *looked_up_ref;
git_repository *repo;
git_oid id;
const char *new_head = "refs/heads/new-head";
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
/* Create and write the new object id reference */
must_fail(git_reference_create_oid(&new_reference, repo, new_head, &id, 0));
/* Ensure the reference can't be looked-up... */
must_fail(git_reference_lookup(&looked_up_ref, repo, new_head));
git_repository_free(repo);
END_TEST
static const char *ref_name = "refs/heads/other";
static const char *ref_master_name = "refs/heads/master";
static const char *ref_branch_name = "refs/heads/branch";
static const char *ref_test_name = "refs/heads/test";
BEGIN_TEST(overwrite0, "Overwrite an existing symbolic reference")
git_reference *ref, *branch_ref;
git_repository *repo;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* The target needds to exist and we need to check the name has changed */
must_pass(git_reference_create_symbolic(&branch_ref, repo, ref_branch_name, ref_master_name, 0));
must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_branch_name, 0));
git_reference_free(ref);
/* Ensure it points to the right place*/
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_branch_name));
git_reference_free(ref);
/* Ensure we can't create it unless we force it to */
must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
close_temp_repo(repo);
git_reference_free(ref);
git_reference_free(branch_ref);
END_TEST
BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
git_reference *ref;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Create it */
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
git_reference_free(ref);
must_pass(git_reference_lookup(&ref, repo, ref_test_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Ensure we can't overwrite unless we force it */
must_fail(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 1));
git_reference_free(ref);
/* Ensure it has been overwritten */
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(!git_oid_cmp(&id, git_reference_oid(ref)));
close_temp_repo(repo);
git_reference_free(ref);
END_TEST
BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symbolic one")
git_reference *ref;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
git_reference_free(ref);
must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_master_name));
close_temp_repo(repo);
git_reference_free(ref);
END_TEST
BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object id one")
git_reference *ref;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
git_reference_free(ref);
/* Create the symbolic ref */
must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
git_reference_free(ref);
/* It shouldn't overwrite unless we tell it to */
must_fail(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 1));
git_reference_free(ref);
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
must_be_true(!git_oid_cmp(git_reference_oid(ref), &id));
close_temp_repo(repo);
git_reference_free(ref);
END_TEST
BEGIN_TEST(pack0, "create a packfile for an empty folder")
git_repository *repo;
git_buf temp_path = GIT_BUF_INIT;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_buf_join_n(&temp_path, '/', 3, repo->path_repository, GIT_REFS_HEADS_DIR, "empty_dir"));
must_pass(git_futils_mkdir_r(temp_path.ptr, NULL, GIT_REFS_DIR_MODE));
git_buf_free(&temp_path);
must_pass(git_reference_packall(repo));
close_temp_repo(repo);
END_TEST
BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
git_repository *repo;
git_reference *reference;
git_buf temp_path = GIT_BUF_INIT;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure a known loose ref can be looked up */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
must_be_true(git_reference_is_packed(reference) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
git_reference_free(reference);
/*
* We are now trying to pack also a loose reference
* called `points_to_blob`, to make sure we can properly
* pack weak tags
*/
must_pass(git_reference_packall(repo));
/* Ensure the packed-refs file exists */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, GIT_PACKEDREFS_FILE));
must_pass(git_path_exists(temp_path.ptr));
/* Ensure the known ref can still be looked up but is now packed */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
must_be_true(git_reference_is_packed(reference));
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
/* Ensure the known ref has been removed from the loose folder structure */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, loose_tag_ref_name));
must_pass(!git_path_exists(temp_path.ptr));
close_temp_repo(repo);
git_reference_free(reference);
git_buf_free(&temp_path);
END_TEST
BEGIN_TEST(rename0, "rename a loose reference")
git_reference *looked_up_ref, *another_looked_up_ref;
git_repository *repo;
git_buf temp_path = GIT_BUF_INIT;
const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu";
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the ref doesn't exist on the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, new_name));
must_pass(!git_path_exists(temp_path.ptr));
/* Retrieval of the reference to rename */
must_pass(git_reference_lookup(&looked_up_ref, repo, loose_tag_ref_name));
/* ... which is indeed loose */
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, new_name, 0));
must_be_true(!strcmp(looked_up_ref->name, new_name));
/* ...It can't be looked-up with the old name... */
must_fail(git_reference_lookup(&another_looked_up_ref, repo, loose_tag_ref_name));
/* ...but the new name works ok... */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, new_name));
must_be_true(!strcmp(another_looked_up_ref->name, new_name));
/* .. the ref is still loose... */
must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref can be found in the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, new_name));
must_pass(git_path_exists(temp_path.ptr));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
END_TEST
BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
git_reference *looked_up_ref, *another_looked_up_ref;
git_repository *repo;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the ref doesn't exist on the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, packed_head_name));
must_pass(!git_path_exists(temp_path.ptr));
/* The reference can however be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* .. and it's packed */
must_be_true(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
must_be_true(!strcmp(looked_up_ref->name, brand_new_name));
/* ...It can't be looked-up with the old name... */
must_fail(git_reference_lookup(&another_looked_up_ref, repo, packed_head_name));
/* ...but the new name works ok... */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, brand_new_name));
must_be_true(!strcmp(another_looked_up_ref->name, brand_new_name));
/* .. the ref is no longer packed... */
must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* ...and the ref now happily lives in the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, brand_new_name));
must_pass(git_path_exists(temp_path.ptr));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
END_TEST
BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference which happens to be in both loose and pack state")
git_reference *looked_up_ref, *another_looked_up_ref;
git_repository *repo;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the other reference exists on the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, packed_test_head_name));
must_pass(git_path_exists(temp_path.ptr));
/* Lookup the other reference */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure it's loose */
must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
git_reference_free(another_looked_up_ref);
/* Lookup the reference to rename */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* Ensure it's packed */
must_be_true(git_reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
/* Lookup the other reference */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure it's loose */
must_be_true(git_reference_is_packed(another_looked_up_ref) == 0);
/* Ensure the other ref still exists on the file system */
must_pass(git_path_exists(temp_path.ptr));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
END_TEST
BEGIN_TEST(rename3, "can not rename a reference with the name of an existing reference")
git_reference *looked_up_ref;
git_repository *repo;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* An existing reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* Can not be renamed to the name of another existing reference. */
must_fail(git_reference_rename(looked_up_ref, packed_test_head_name, 0));
git_reference_free(looked_up_ref);
/* Failure to rename it hasn't corrupted its state */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
must_be_true(!strcmp(looked_up_ref->name, packed_head_name));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
git_reference *looked_up_ref;
git_repository *repo;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* An existing oid reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
/* Can not be renamed with an invalid name. */
must_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
/* Can not be renamed outside of the refs hierarchy. */
must_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
/* Failure to rename it hasn't corrupted its state */
git_reference_free(looked_up_ref);
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
must_be_true(!strcmp(looked_up_ref->name, packed_test_head_name));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename5, "can force-rename a packed reference with the name of an existing loose and packed reference")
git_reference *looked_up_ref;
git_repository *repo;
git_oid oid;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* An existing reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
git_oid_cpy(&oid, git_reference_oid(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
must_pass(git_reference_rename(looked_up_ref, packed_test_head_name, 1));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
must_be_true(!strcmp(looked_up_ref->name, packed_test_head_name));
must_be_true(!git_oid_cmp(&oid, git_reference_oid(looked_up_ref)));
git_reference_free(looked_up_ref);
/* And that the previous one doesn't exist any longer */
must_fail(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
close_temp_repo(repo);
END_TEST
BEGIN_TEST(rename6, "can force-rename a loose reference with the name of an existing loose reference")
git_reference *looked_up_ref;
git_repository *repo;
git_oid oid;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* An existing reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, "refs/heads/br2"));
git_oid_cpy(&oid, git_reference_oid(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
must_pass(git_reference_rename(looked_up_ref, "refs/heads/test", 1));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
must_pass(git_reference_lookup(&looked_up_ref, repo, "refs/heads/test"));
must_be_true(!strcmp(looked_up_ref->name, "refs/heads/test"));
must_be_true(!git_oid_cmp(&oid, git_reference_oid(looked_up_ref)));
git_reference_free(looked_up_ref);
/* And that the previous one doesn't exist any longer */
must_fail(git_reference_lookup(&looked_up_ref, repo, "refs/heads/br2"));
close_temp_repo(repo);
git_reference_free(looked_up_ref);
END_TEST
static const char *ref_one_name = "refs/heads/one/branch";
static const char *ref_one_name_new = "refs/heads/two/branch";
static const char *ref_two_name = "refs/heads/two";
BEGIN_TEST(rename7, "can not overwrite name of existing reference")
git_reference *ref, *ref_one, *ref_one_new, *ref_two;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
must_pass(git_reference_create_oid(&ref_one, repo, ref_one_name, &id, 0));
must_pass(git_reference_create_oid(&ref_two, repo, ref_two_name, &id, 0));
/* Pack everything */
must_pass(git_reference_packall(repo));
/* Attempt to create illegal reference */
must_fail(git_reference_create_oid(&ref_one_new, repo, ref_one_name_new, &id, 0));
/* Illegal reference couldn't be created so this is supposed to fail */
must_fail(git_reference_lookup(&ref_one_new, repo, ref_one_name_new));
close_temp_repo(repo);
git_reference_free(ref);
git_reference_free(ref_one);
git_reference_free(ref_one_new);
git_reference_free(ref_two);
END_TEST
static const char *ref_two_name_new = "refs/heads/two/two";
BEGIN_TEST(rename8, "can be renamed to a new name prefixed with the old name")
git_reference *ref, *ref_two, *looked_up_ref;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
must_pass(git_reference_create_oid(&ref_two, repo, ref_two_name, &id, 0));
/* An existing reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, ref_two_name));
/* Can be rename to a new name starting with the old name. */
must_pass(git_reference_rename(looked_up_ref, ref_two_name_new, 0));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
must_pass(git_reference_lookup(&looked_up_ref, repo, ref_two_name_new));
must_be_true(!strcmp(looked_up_ref->name, ref_two_name_new));
git_reference_free(looked_up_ref);
must_fail(git_reference_lookup(&looked_up_ref, repo, ref_two_name));
close_temp_repo(repo);
git_reference_free(ref);
git_reference_free(ref_two);
git_reference_free(looked_up_ref);
END_TEST
BEGIN_TEST(rename9, "can move a reference to a upper reference hierarchy")
git_reference *ref, *ref_two, *looked_up_ref;
git_repository *repo;
git_oid id;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_lookup(&ref, repo, ref_master_name));
must_be_true(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
must_pass(git_reference_create_oid(&ref_two, repo, ref_two_name_new, &id, 0));
git_reference_free(ref_two);
/* An existing reference... */
must_pass(git_reference_lookup(&looked_up_ref, repo, ref_two_name_new));
/* Can be renamed upward the reference tree. */
must_pass(git_reference_rename(looked_up_ref, ref_two_name, 0));
git_reference_free(looked_up_ref);
/* Check we actually renamed it */
must_pass(git_reference_lookup(&looked_up_ref, repo, ref_two_name));
must_be_true(!strcmp(looked_up_ref->name, ref_two_name));
git_reference_free(looked_up_ref);
must_fail(git_reference_lookup(&looked_up_ref, repo, ref_two_name_new));
git_reference_free(ref);
git_reference_free(looked_up_ref);
close_temp_repo(repo);
END_TEST
BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove both tracks in the filesystem")
git_reference *looked_up_ref, *another_looked_up_ref;
git_repository *repo;
git_buf temp_path = GIT_BUF_INIT;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the loose reference exists on the file system */
must_pass(git_buf_joinpath(&temp_path, repo->path_repository, packed_test_head_name));
must_pass(git_path_exists(temp_path.ptr));
/* Lookup the reference */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
/* Ensure it's the loose version that has been found */
must_be_true(git_reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is deleted... */
must_pass(git_reference_delete(looked_up_ref));
/* Looking up the reference once again should not retrieve it */
must_fail(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure the loose reference doesn't exist any longer on the file system */
must_pass(!git_path_exists(temp_path.ptr));
close_temp_repo(repo);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
END_TEST
BEGIN_TEST(delete1, "can delete a just packed reference")
git_reference *ref;
git_repository *repo;
git_oid id;
const char *new_ref = "refs/heads/new_ref";
git_oid_fromstr(&id, current_master_tip);
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Create and write the new object id reference */
must_pass(git_reference_create_oid(&ref, repo, new_ref, &id, 0));
git_reference_free(ref);
/* Lookup the reference */
must_pass(git_reference_lookup(&ref, repo, new_ref));
/* Ensure it's a loose reference */
must_be_true(git_reference_is_packed(ref) == 0);
/* Pack all existing references */
must_pass(git_reference_packall(repo));
/* Reload the reference from disk */
must_pass(git_reference_reload(ref));
/* Ensure it's a packed reference */
must_be_true(git_reference_is_packed(ref) == 1);
/* This should pass */
must_pass(git_reference_delete(ref));
close_temp_repo(repo);
END_TEST
static int ensure_refname_normalized(int is_oid_ref, const char *input_refname, const char *expected_refname)
{
int error = GIT_SUCCESS;
char buffer_out[GIT_REFNAME_MAX];
if (is_oid_ref)
error = git_reference__normalize_name_oid(buffer_out, sizeof(buffer_out), input_refname);
else
error = git_reference__normalize_name(buffer_out, sizeof(buffer_out), input_refname);
if (error < GIT_SUCCESS)
return error;
if (expected_refname == NULL)
return error;
if (strcmp(buffer_out, expected_refname))
error = GIT_ERROR;
return error;
}
#define OID_REF 1
#define SYM_REF 0
BEGIN_TEST(normalize0, "normalize a direct (OID) reference name")
must_fail(ensure_refname_normalized(OID_REF, "a", NULL));
must_fail(ensure_refname_normalized(OID_REF, "", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/a/", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/a.", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/a.lock", NULL));
must_pass(ensure_refname_normalized(OID_REF, "refs/dummy/a", NULL));
must_pass(ensure_refname_normalized(OID_REF, "refs/stash", NULL));
must_pass(ensure_refname_normalized(OID_REF, "refs/tags/a", "refs/tags/a"));
must_pass(ensure_refname_normalized(OID_REF, "refs/heads/a/b", "refs/heads/a/b"));
must_pass(ensure_refname_normalized(OID_REF, "refs/heads/a./b", "refs/heads/a./b"));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/foo?bar", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads\foo", NULL));
must_pass(ensure_refname_normalized(OID_REF, "refs/heads/v@ation", "refs/heads/v@ation"));
must_pass(ensure_refname_normalized(OID_REF, "refs///heads///a", "refs/heads/a"));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/.a/b", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/foo/../bar", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/foo..bar", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/./foo", NULL));
must_fail(ensure_refname_normalized(OID_REF, "refs/heads/v@{ation", NULL));
END_TEST
BEGIN_TEST(normalize1, "normalize a symbolic reference name")
must_pass(ensure_refname_normalized(SYM_REF, "a", "a"));
must_pass(ensure_refname_normalized(SYM_REF, "a/b", "a/b"));
must_pass(ensure_refname_normalized(SYM_REF, "refs///heads///a", "refs/heads/a"));
must_fail(ensure_refname_normalized(SYM_REF, "", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "heads\foo", NULL));
END_TEST
/* Ported from JGit, BSD licence.
* See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
BEGIN_TEST(normalize2, "tests borrowed from JGit")
/* EmptyString */
must_fail(ensure_refname_normalized(SYM_REF, "", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "/", NULL));
/* MustHaveTwoComponents */
must_fail(ensure_refname_normalized(OID_REF, "master", NULL));
must_pass(ensure_refname_normalized(SYM_REF, "heads/master", "heads/master"));
/* ValidHead */
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/master", "refs/heads/master"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/pu", "refs/heads/pu"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/z", "refs/heads/z"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/FoO", "refs/heads/FoO"));
/* ValidTag */
must_pass(ensure_refname_normalized(SYM_REF, "refs/tags/v1.0", "refs/tags/v1.0"));
/* NoLockSuffix */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master.lock", NULL));
/* NoDirectorySuffix */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master/", NULL));
/* NoSpace */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/i haz space", NULL));
/* NoAsciiControlCharacters */
{
char c;
char buffer[GIT_REFNAME_MAX];
for (c = '\1'; c < ' '; c++) {
strncpy(buffer, "refs/heads/mast", 15);
strncpy(buffer + 15, (const char *)&c, 1);
strncpy(buffer + 16, "er", 2);
buffer[18 - 1] = '\0';
must_fail(ensure_refname_normalized(SYM_REF, buffer, NULL));
}
}
/* NoBareDot */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/.", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/..", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/./master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/../master", NULL));
/* NoLeadingOrTrailingDot */
must_fail(ensure_refname_normalized(SYM_REF, ".", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/.bar", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/..bar", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/bar.", NULL));
/* ContainsDot */
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r"));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master..pu", NULL));
/* NoMagicRefCharacters */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master^", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/^master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "^refs/heads/master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master~", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/~master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "~refs/heads/master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master:", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/:master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, ":refs/heads/master", NULL));
/* ShellGlob */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master?", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/?master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "?refs/heads/master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master[", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/[master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "[refs/heads/master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master*", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/*master", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "*refs/heads/master", NULL));
/* ValidSpecialCharacters */
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/!", "refs/heads/!"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/\"", "refs/heads/\""));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/#", "refs/heads/#"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/$", "refs/heads/$"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/%", "refs/heads/%"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/&", "refs/heads/&"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/'", "refs/heads/'"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/(", "refs/heads/("));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/)", "refs/heads/)"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/+", "refs/heads/+"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/,", "refs/heads/,"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/-", "refs/heads/-"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/;", "refs/heads/;"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/<", "refs/heads/<"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/=", "refs/heads/="));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/>", "refs/heads/>"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/@", "refs/heads/@"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/]", "refs/heads/]"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/_", "refs/heads/_"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/`", "refs/heads/`"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/{", "refs/heads/{"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/|", "refs/heads/|"));
must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/}", "refs/heads/}"));
// This is valid on UNIX, but not on Windows
// hence we make in invalid due to non-portability
//
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/\\", NULL));
/* UnicodeNames */
/*
* Currently this fails.
* must_pass(ensure_refname_normalized(SYM_REF, "refs/heads/\u00e5ngstr\u00f6m", "refs/heads/\u00e5ngstr\u00f6m"));
*/
/* RefLogQueryIsValidRef */
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master@{1}", NULL));
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master@{1.hour.ago}", NULL));
END_TEST
BEGIN_TEST(list0, "try to list all the references in our test repo")
git_repository *repo;
git_strarray ref_list;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_listall(&ref_list, repo, GIT_REF_LISTALL));
/*{
unsigned short i;
for (i = 0; i < ref_list.count; ++i)
printf("# %s\n", ref_list.strings[i]);
}*/
/* We have exactly 9 refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
must_be_true(ref_list.count == 9);
git_strarray_free(&ref_list);
git_repository_free(repo);
END_TEST
BEGIN_TEST(list1, "try to list only the symbolic references")
git_repository *repo;
git_strarray ref_list;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_listall(&ref_list, repo, GIT_REF_SYMBOLIC));
must_be_true(ref_list.count == 0); /* no symrefs in the test repo */
git_strarray_free(&ref_list);
git_repository_free(repo);
END_TEST
static const char *new_ref = "refs/heads/test-reflog";
#define commit_msg "commit: bla bla"
static int assert_signature(git_signature *expected, git_signature *actual)
{
if (actual == NULL)
return GIT_ERROR;
if (strcmp(expected->name, actual->name) != 0)
return GIT_ERROR;
if (strcmp(expected->email, actual->email) != 0)
return GIT_ERROR;
if (expected->when.offset != actual->when.offset)
return GIT_ERROR;
if (expected->when.time != actual->when.time)
return GIT_ERROR;
return GIT_SUCCESS;
}
BEGIN_TEST(reflog0, "write a reflog for a given reference and ensure it can be read back")
git_repository *repo, *repo2;
git_reference *ref, *lookedup_ref;
git_oid oid;
git_signature *committer;
git_reflog *reflog;
git_reflog_entry *entry;
char oid_str[GIT_OID_HEXSZ+1];
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Create a new branch pointing at the HEAD */
git_oid_fromstr(&oid, current_master_tip);
must_pass(git_reference_create_oid(&ref, repo, new_ref, &oid, 0));
git_reference_free(ref);
must_pass(git_reference_lookup(&ref, repo, new_ref));
must_pass(git_signature_now(&committer, "foo", "foo@bar"));
must_pass(git_reflog_write(ref, NULL, committer, NULL));
must_fail(git_reflog_write(ref, NULL, committer, "no ancestor NULL for an existing reflog"));
must_fail(git_reflog_write(ref, NULL, committer, "no\nnewline"));
must_pass(git_reflog_write(ref, &oid, committer, commit_msg));
git_repository_free(repo);
/* Reopen a new instance of the repository */
must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
/* Lookup the preivously created branch */
must_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref));
/* Read and parse the reflog for this branch */
must_pass(git_reflog_read(&reflog, lookedup_ref));
must_be_true(reflog->entries.length == 2);
entry = (git_reflog_entry *)git_vector_get(&reflog->entries, 0);
must_pass(assert_signature(committer, entry->committer));
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_old);
must_be_true(strcmp("0000000000000000000000000000000000000000", oid_str) == 0);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_cur);
must_be_true(strcmp(current_master_tip, oid_str) == 0);
must_be_true(entry->msg == NULL);
entry = (git_reflog_entry *)git_vector_get(&reflog->entries, 1);
must_pass(assert_signature(committer, entry->committer));
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_old);
must_be_true(strcmp(current_master_tip, oid_str) == 0);
git_oid_tostr(oid_str, GIT_OID_HEXSZ+1, &entry->oid_cur);
must_be_true(strcmp(current_master_tip, oid_str) == 0);
must_be_true(strcmp(commit_msg, entry->msg) == 0);
git_signature_free(committer);
git_reflog_free(reflog);
close_temp_repo(repo2);
git_reference_free(ref);
git_reference_free(lookedup_ref);
END_TEST
BEGIN_TEST(reflog1, "avoid writing an obviously wrong reflog")
git_repository *repo;
git_reference *ref;
git_oid oid;
git_signature *committer;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Create a new branch pointing at the HEAD */
git_oid_fromstr(&oid, current_master_tip);
must_pass(git_reference_create_oid(&ref, repo, new_ref, &oid, 0));
git_reference_free(ref);
must_pass(git_reference_lookup(&ref, repo, new_ref));
must_pass(git_signature_now(&committer, "foo", "foo@bar"));
/* Write the reflog for the new branch */
must_pass(git_reflog_write(ref, NULL, committer, NULL));
/* Try to update the reflog with wrong information:
* It's no new reference, so the ancestor OID cannot
* be NULL. */
must_fail(git_reflog_write(ref, NULL, committer, NULL));
git_signature_free(committer);
close_temp_repo(repo);
git_reference_free(ref);
END_TEST
BEGIN_SUITE(refs)
ADD_TEST(readtag0);
ADD_TEST(readtag1);
ADD_TEST(readsym0);
ADD_TEST(readsym1);
ADD_TEST(readsym2);
ADD_TEST(readsym3);
ADD_TEST(readpacked0);
ADD_TEST(readpacked1);
ADD_TEST(create0);
ADD_TEST(create1);
ADD_TEST(create2);
ADD_TEST(create3);
ADD_TEST(overwrite0);
ADD_TEST(overwrite1);
ADD_TEST(overwrite2);
ADD_TEST(overwrite3);
ADD_TEST(normalize0);
ADD_TEST(normalize1);
ADD_TEST(normalize2);
ADD_TEST(pack0);
ADD_TEST(pack1);
ADD_TEST(rename0);
ADD_TEST(rename1);
ADD_TEST(rename2);
ADD_TEST(rename3);
ADD_TEST(rename4);
ADD_TEST(rename5);
ADD_TEST(rename6);
ADD_TEST(rename7);
ADD_TEST(rename8);
ADD_TEST(rename9);
ADD_TEST(delete0);
ADD_TEST(delete1);
ADD_TEST(list0);
ADD_TEST(list1);
ADD_TEST(reflog0);
ADD_TEST(reflog1);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "odb.h"
#include "git2/odb_backend.h"
#include "repository.h"
#define EMPTY_BARE_REPOSITORY_FOLDER TEST_RESOURCES "/empty_bare.git/"
#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git"
#define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME
#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub"
#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub"
#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub"
#define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo"
#define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub"
#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub"
#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub"
#define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1"
#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2"
#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3"
#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo"
static int ensure_repository_discover(const char *start_path, const char *ceiling_dirs, const char *expected_path)
{
int error;
char found_path[GIT_PATH_MAX];
error = git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs);
//across_fs is always 0 as we can't automate the filesystem change tests
if (error < GIT_SUCCESS)
return error;
return strcmp(found_path, expected_path) ? GIT_ERROR : GIT_SUCCESS;
}
static int write_file(const char *path, const char *content)
{
int error;
git_file file;
if (git_path_exists(path) == GIT_SUCCESS) {
error = p_unlink(path);
if (error < GIT_SUCCESS)
return error;
}
file = git_futils_creat_withpath(path, 0777, 0666);
if (file < GIT_SUCCESS)
return file;
error = p_write(file, content, strlen(content) * sizeof(char));
p_close(file);
return error;
}
//no check is performed on ceiling_dirs length, so be sure it's long enough
static int append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
{
git_buf pretty_path = GIT_BUF_INIT;
int error;
char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' };
error = git_path_prettify_dir(&pretty_path, path, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to append ceiling directory.");
if (ceiling_dirs->size > 0)
git_buf_puts(ceiling_dirs, ceiling_separator);
git_buf_puts(ceiling_dirs, pretty_path.ptr);
git_buf_free(&pretty_path);
return git_buf_lasterror(ceiling_dirs);
}
BEGIN_TEST(discover0, "test discover")
git_repository *repo;
git_buf ceiling_dirs_buf = GIT_BUF_INIT;
const char *ceiling_dirs;
char repository_path[GIT_PATH_MAX];
char sub_repository_path[GIT_PATH_MAX];
char found_path[GIT_PATH_MAX];
const mode_t mode = 0777;
git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode);
must_pass(append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER));
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
must_be_true(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO);
must_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
must_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
git_repository_free(repo);
must_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
must_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path));
must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"));
must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, NULL, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:"));
must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, NULL, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"));
must_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode));
must_pass(write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
must_pass(append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER));
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
must_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
//.gitfile redirection should not be affected by ceiling directories
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path));
must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
git_repository_free(repo);
git_buf_free(&ceiling_dirs_buf);
END_TEST
BEGIN_SUITE(repository)
ADD_TEST(discover0);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "cache.h"
typedef struct {
git_cached_obj cached;
unsigned int __dummy;
} ttest_obj;
BEGIN_TEST(cache0, "run several threads polling the cache at the same time")
END_TEST
BEGIN_SUITE(threads)
ADD_TEST(cache0);
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include <git2.h>
#include "buffer.h"
const char *test_string = "Have you seen that? Have you seeeen that??";
BEGIN_TEST(buf0, "check that resizing works properly")
git_buf buf = GIT_BUF_INIT;
git_buf_puts(&buf, test_string);
must_be_true(git_buf_oom(&buf) == 0);
must_be_true(strcmp(git_buf_cstr(&buf), test_string) == 0);
git_buf_puts(&buf, test_string);
must_be_true(strlen(git_buf_cstr(&buf)) == strlen(test_string) * 2);
git_buf_free(&buf);
END_TEST
BEGIN_TEST(buf1, "check that printf works properly")
git_buf buf = GIT_BUF_INIT;
git_buf_printf(&buf, "%s %s %d ", "shoop", "da", 23);
must_be_true(git_buf_oom(&buf) == 0);
must_be_true(strcmp(git_buf_cstr(&buf), "shoop da 23 ") == 0);
git_buf_printf(&buf, "%s %d", "woop", 42);
must_be_true(git_buf_oom(&buf) == 0);
must_be_true(strcmp(git_buf_cstr(&buf), "shoop da 23 woop 42") == 0);
git_buf_free(&buf);
END_TEST
BEGIN_SUITE(buffers)
ADD_TEST(buf0)
ADD_TEST(buf1)
END_SUITE
/*
* 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 "test_lib.h"
#include "test_helpers.h"
#include "fileops.h"
#include "git2/status.h"
static const char *test_blob_oid = "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a";
#define STATUS_WORKDIR_FOLDER TEST_RESOURCES "/status/"
#define STATUS_REPOSITORY_TEMP_FOLDER TEMP_REPO_FOLDER ".gitted/"
static int file_create(const char *filename, const char *content)
{
int fd;
fd = p_creat(filename, 0666);
if (fd == 0)
return GIT_ERROR;
if (p_write(fd, content, strlen(content)) != 0)
return GIT_ERROR;
if (p_close(fd) != 0)
return GIT_ERROR;
return GIT_SUCCESS;
}
BEGIN_TEST(file0, "test retrieving OID from a file apart from the ODB")
git_oid expected_id, actual_id;
char filename[] = "new_file";
must_pass(file_create(filename, "new_file\n\0"));
must_pass(git_odb_hashfile(&actual_id, filename, GIT_OBJ_BLOB));
must_pass(git_oid_fromstr(&expected_id, test_blob_oid));
must_be_true(git_oid_cmp(&expected_id, &actual_id) == 0);
must_pass(p_unlink(filename));
END_TEST
static const char *entry_paths0[] = {
"file_deleted",
"ignored_file",
"modified_file",
"new_file",
"staged_changes",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_file_deleted",
"staged_delete_modified_file",
"staged_new_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"subdir/deleted_file",
"subdir/modified_file",
"subdir/new_file",
};
static const unsigned int entry_statuses0[] = {
GIT_STATUS_WT_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_DELETED,
GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_DELETED,
GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
};
#define ENTRY_COUNT0 15
struct status_entry_counts {
int wrong_status_flags_count;
int wrong_sorted_path;
int entry_count;
const unsigned int* expected_statuses;
const char** expected_paths;
int expected_entry_count;
};
static int status_cb(const char *path, unsigned int status_flags, void *payload)
{
struct status_entry_counts *counts = (struct status_entry_counts *)payload;
if (counts->entry_count >= counts->expected_entry_count) {
counts->wrong_status_flags_count++;
goto exit;
}
if (strcmp(path, counts->expected_paths[counts->entry_count])) {
counts->wrong_sorted_path++;
goto exit;
}
if (status_flags != counts->expected_statuses[counts->entry_count])
counts->wrong_status_flags_count++;
exit:
counts->entry_count++;
return GIT_SUCCESS;
}
BEGIN_TEST(statuscb0, "test retrieving status for worktree of repository")
git_repository *repo;
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
memset(&counts, 0x0, sizeof(struct status_entry_counts));
counts.expected_entry_count = ENTRY_COUNT0;
counts.expected_paths = entry_paths0;
counts.expected_statuses = entry_statuses0;
must_pass(git_status_foreach(repo, status_cb, &counts));
must_be_true(counts.entry_count == counts.expected_entry_count);
must_be_true(counts.wrong_status_flags_count == 0);
must_be_true(counts.wrong_sorted_path == 0);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
static int status_cb1(const char *path, unsigned int status_flags, void *payload)
{
int *count = (int *)payload;;
GIT_UNUSED(path);
GIT_UNUSED(status_flags);
(*count)++;
return GIT_SUCCESS;
}
BEGIN_TEST(statuscb1, "test retrieving status for a worktree of an empty repository")
git_repository *repo;
int count = 0;
must_pass(copydir_recurs(EMPTY_REPOSITORY_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(remove_placeholders(TEST_STD_REPO_FOLDER, "dummy-marker.txt"));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
must_pass(git_status_foreach(repo, status_cb1, &count));
must_be_true(count == 0);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
static const char *entry_paths2[] = {
"current_file",
"file_deleted",
"ignored_file",
"modified_file",
"staged_changes",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_file_deleted",
"staged_delete_modified_file",
"staged_new_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"subdir/current_file",
"subdir/deleted_file",
"subdir/modified_file",
};
static const unsigned int entry_statuses2[] = {
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED,
};
#define ENTRY_COUNT2 15
BEGIN_TEST(statuscb2, "test retrieving status for a purged worktree of an valid repository")
git_repository *repo;
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
/* Purging the working */
must_pass(p_unlink(TEMP_REPO_FOLDER "current_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "modified_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "new_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "staged_changes"));
must_pass(p_unlink(TEMP_REPO_FOLDER "staged_changes_modified_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "staged_delete_modified_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "staged_new_file"));
must_pass(p_unlink(TEMP_REPO_FOLDER "staged_new_file_modified_file"));
must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER "subdir", 1));
memset(&counts, 0x0, sizeof(struct status_entry_counts));
counts.expected_entry_count = ENTRY_COUNT2;
counts.expected_paths = entry_paths2;
counts.expected_statuses = entry_statuses2;
must_pass(git_status_foreach(repo, status_cb, &counts));
must_be_true(counts.entry_count == counts.expected_entry_count);
must_be_true(counts.wrong_status_flags_count == 0);
must_be_true(counts.wrong_sorted_path == 0);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
static const char *entry_paths3[] = {
".HEADER",
"42-is-not-prime.sigh",
"README.md",
"current_file",
"current_file/current_file",
"current_file/modified_file",
"current_file/new_file",
"file_deleted",
"ignored_file",
"modified_file",
"new_file",
"staged_changes",
"staged_changes_file_deleted",
"staged_changes_modified_file",
"staged_delete_file_deleted",
"staged_delete_modified_file",
"staged_new_file",
"staged_new_file_deleted_file",
"staged_new_file_modified_file",
"subdir",
"subdir/current_file",
"subdir/deleted_file",
"subdir/modified_file",
};
static const unsigned int entry_statuses3[] = {
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW,
GIT_STATUS_WT_NEW,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED,
GIT_STATUS_WT_DELETED,
};
#define ENTRY_COUNT3 23
BEGIN_TEST(statuscb3, "test retrieving status for a worktree where a file and a subdir have been renamed and some files have been added")
git_repository *repo;
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
must_pass(p_rename(TEMP_REPO_FOLDER "current_file", TEMP_REPO_FOLDER "swap"));
must_pass(p_rename(TEMP_REPO_FOLDER "subdir", TEMP_REPO_FOLDER "current_file"));
must_pass(p_rename(TEMP_REPO_FOLDER "swap", TEMP_REPO_FOLDER "subdir"));
must_pass(file_create(TEMP_REPO_FOLDER ".HEADER", "dummy"));
must_pass(file_create(TEMP_REPO_FOLDER "42-is-not-prime.sigh", "dummy"));
must_pass(file_create(TEMP_REPO_FOLDER "README.md", "dummy"));
memset(&counts, 0x0, sizeof(struct status_entry_counts));
counts.expected_entry_count = ENTRY_COUNT3;
counts.expected_paths = entry_paths3;
counts.expected_statuses = entry_statuses3;
must_pass(git_status_foreach(repo, status_cb, &counts));
must_be_true(counts.entry_count == counts.expected_entry_count);
must_be_true(counts.wrong_status_flags_count == 0);
must_be_true(counts.wrong_sorted_path == 0);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_TEST(singlestatus0, "test retrieving status for single file")
git_repository *repo;
unsigned int status_flags;
int i;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
for (i = 0; i < ENTRY_COUNT0; ++i) {
must_pass(git_status_file(&status_flags, repo, entry_paths0[i]));
must_be_true(status_flags == entry_statuses0[i]);
}
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_TEST(singlestatus1, "test retrieving status for nonexistent file")
git_repository *repo;
unsigned int status_flags;
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
// "nonexistent" does not exist in HEAD, Index or the worktree
error = git_status_file(&status_flags, repo, "nonexistent");
must_be_true(error == GIT_ENOTFOUND);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_TEST(singlestatus2, "test retrieving status for a non existent file in an empty repository")
git_repository *repo;
unsigned int status_flags;
int error;
must_pass(copydir_recurs(EMPTY_REPOSITORY_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(remove_placeholders(TEST_STD_REPO_FOLDER, "dummy-marker.txt"));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
error = git_status_file(&status_flags, repo, "nonexistent");
must_be_true(error == GIT_ENOTFOUND);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_TEST(singlestatus3, "test retrieving status for a new file in an empty repository")
git_repository *repo;
unsigned int status_flags;
git_buf file_path = GIT_BUF_INIT;
char filename[] = "new_file";
int fd;
must_pass(copydir_recurs(EMPTY_REPOSITORY_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(remove_placeholders(TEST_STD_REPO_FOLDER, "dummy-marker.txt"));
must_pass(git_buf_joinpath(&file_path, TEMP_REPO_FOLDER, filename));
fd = p_creat(file_path.ptr, 0666);
must_pass(fd);
must_pass(p_write(fd, "new_file\n", 9));
must_pass(p_close(fd));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
must_pass(git_status_file(&status_flags, repo, filename));
must_be_true(status_flags == GIT_STATUS_WT_NEW);
git_repository_free(repo);
git_buf_free(&file_path);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_TEST(singlestatus4, "can't determine the status for a folder")
git_repository *repo;
unsigned int status_flags;
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
error = git_status_file(&status_flags, repo, "subdir");
must_be_true(error == GIT_EINVALIDPATH);
git_repository_free(repo);
git_futils_rmdir_r(TEMP_REPO_FOLDER, 1);
END_TEST
BEGIN_SUITE(status)
ADD_TEST(file0);
ADD_TEST(statuscb0);
ADD_TEST(statuscb1);
ADD_TEST(statuscb2);
ADD_TEST(statuscb3);
ADD_TEST(singlestatus0);
ADD_TEST(singlestatus1);
ADD_TEST(singlestatus2);
ADD_TEST(singlestatus3);
ADD_TEST(singlestatus4);
END_SUITE
/*
* 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 "test_helpers.h"
#include "fileops.h"
int write_object_data(char *file, void *data, size_t len)
{
git_file fd;
int ret;
if ((fd = p_creat(file, S_IREAD | S_IWRITE)) < 0)
return -1;
ret = p_write(fd, data, len);
p_close(fd);
return ret;
}
int write_object_files(const char *odb_dir, object_data *d)
{
if (p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
fprintf(stderr, " (already exists)");
fprintf(stderr, "\n");
return -1;
}
if ((p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0) && (errno != EEXIST)) {
fprintf(stderr, "can't make object directory \"%s\"\n", d->dir);
return -1;
}
if (write_object_data(d->file, d->bytes, d->blen) < 0) {
fprintf(stderr, "can't write object file \"%s\"\n", d->file);
return -1;
}
return 0;
}
int remove_object_files(const char *odb_dir, object_data *d)
{
if (p_unlink(d->file) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", d->file);
return -1;
}
if ((p_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove object directory \"%s\"\n", d->dir);
return -1;
}
if (p_rmdir(odb_dir) < 0) {
fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir);
return -1;
}
return 0;
}
void locate_loose_object(const char *repository_folder, git_object *object, char **out, char **out_folder)
{
static const char *objects_folder = "objects/";
char *ptr, *full_path, *top_folder;
int path_length, objects_length;
assert(repository_folder && object);
objects_length = strlen(objects_folder);
path_length = strlen(repository_folder);
ptr = full_path = git__malloc(path_length + objects_length + GIT_OID_HEXSZ + 3);
strcpy(ptr, repository_folder);
strcpy(ptr + path_length, objects_folder);
ptr = top_folder = ptr + path_length + objects_length;
*ptr++ = '/';
git_oid_pathfmt(ptr, git_object_id(object));
ptr += GIT_OID_HEXSZ + 1;
*ptr = 0;
*out = full_path;
if (out_folder)
*out_folder = top_folder;
}
int loose_object_mode(const char *repository_folder, git_object *object)
{
char *object_path;
struct stat st;
locate_loose_object(repository_folder, object, &object_path, NULL);
if (p_stat(object_path, &st) < 0)
return 0;
free(object_path);
return st.st_mode;
}
int loose_object_dir_mode(const char *repository_folder, git_object *object)
{
char *object_path;
size_t pos;
struct stat st;
locate_loose_object(repository_folder, object, &object_path, NULL);
pos = strlen(object_path);
while (pos--) {
if (object_path[pos] == '/') {
object_path[pos] = 0;
break;
}
}
if (p_stat(object_path, &st) < 0)
return 0;
free(object_path);
return st.st_mode;
}
int remove_loose_object(const char *repository_folder, git_object *object)
{
char *full_path, *top_folder;
locate_loose_object(repository_folder, object, &full_path, &top_folder);
if (p_unlink(full_path) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", full_path);
return -1;
}
*top_folder = 0;
if ((p_rmdir(full_path) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove object directory \"%s\"\n", full_path);
return -1;
}
git__free(full_path);
return GIT_SUCCESS;
}
int cmp_objects(git_rawobj *o, object_data *d)
{
if (o->type != git_object_string2type(d->type))
return -1;
if (o->len != d->dlen)
return -1;
if ((o->len > 0) && (memcmp(o->data, d->data, o->len) != 0))
return -1;
return 0;
}
int copy_file(const char *src, const char *dst)
{
git_buf source_buf = GIT_BUF_INIT;
git_file dst_fd;
int error = GIT_ERROR;
if (git_futils_readbuffer(&source_buf, src) < GIT_SUCCESS)
return GIT_ENOTFOUND;
dst_fd = git_futils_creat_withpath(dst, 0777, 0666);
if (dst_fd < 0)
goto cleanup;
error = p_write(dst_fd, source_buf.ptr, source_buf.size);
cleanup:
git_buf_free(&source_buf);
p_close(dst_fd);
return error;
}
int cmp_files(const char *a, const char *b)
{
git_buf buf_a = GIT_BUF_INIT;
git_buf buf_b = GIT_BUF_INIT;
int error = GIT_ERROR;
if (git_futils_readbuffer(&buf_a, a) < GIT_SUCCESS)
return GIT_ERROR;
if (git_futils_readbuffer(&buf_b, b) < GIT_SUCCESS) {
git_buf_free(&buf_a);
return GIT_ERROR;
}
if (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size))
error = GIT_SUCCESS;
git_buf_free(&buf_a);
git_buf_free(&buf_b);
return error;
}
typedef struct {
git_buf src;
size_t src_baselen;
git_buf dst;
size_t dst_baselen;
} copydir_data;
static int copy_filesystem_element_recurs(void *_data, git_buf *source)
{
copydir_data *data = (copydir_data *)_data;
git_buf_truncate(&data->dst, data->dst_baselen);
git_buf_puts(&data->dst, source->ptr + data->src_baselen);
if (git_path_isdir(source->ptr) == GIT_SUCCESS)
return git_path_direach(source, copy_filesystem_element_recurs, _data);
else
return copy_file(source->ptr, data->dst.ptr);
}
int copydir_recurs(
const char *source_directory_path,
const char *destination_directory_path)
{
int error;
copydir_data data = { GIT_BUF_INIT, 0, GIT_BUF_INIT, 0 };
/* Source has to exist, Destination hast to _not_ exist */
if (git_path_isdir(source_directory_path) != GIT_SUCCESS ||
git_path_isdir(destination_directory_path) == GIT_SUCCESS)
return GIT_EINVALIDPATH;
git_buf_joinpath(&data.src, source_directory_path, "");
data.src_baselen = data.src.size;
git_buf_joinpath(&data.dst, destination_directory_path, "");
data.dst_baselen = data.dst.size;
error = copy_filesystem_element_recurs(&data, &data.src);
git_buf_free(&data.src);
git_buf_free(&data.dst);
return error;
}
int open_temp_repo(git_repository **repo, const char *path)
{
int error;
if ((error = copydir_recurs(path, TEMP_REPO_FOLDER)) < GIT_SUCCESS)
return error;
return git_repository_open(repo, TEMP_REPO_FOLDER);
}
void close_temp_repo(git_repository *repo)
{
git_repository_free(repo);
if (git_futils_rmdir_r(TEMP_REPO_FOLDER, 1) < GIT_SUCCESS) {
printf("\nFailed to remove temporary folder. Aborting test suite.\n");
exit(-1);
}
}
typedef struct {
const char *filename;
size_t filename_len;
} remove_data;
static int remove_placeholders_recurs(void *_data, git_buf *path)
{
remove_data *data = (remove_data *)_data;
size_t pathlen;
if (!git_path_isdir(path->ptr))
return git_path_direach(path, remove_placeholders_recurs, data);
pathlen = path->size;
if (pathlen < data->filename_len)
return GIT_SUCCESS;
/* if path ends in '/'+filename (or equals filename) */
if (!strcmp(data->filename, path->ptr + pathlen - data->filename_len) &&
(pathlen == data->filename_len ||
path->ptr[pathlen - data->filename_len - 1] == '/'))
return p_unlink(path->ptr);
return GIT_SUCCESS;
}
int remove_placeholders(const char *directory_path, const char *filename)
{
int error;
remove_data data;
git_buf buffer = GIT_BUF_INIT;
if (git_path_isdir(directory_path))
return GIT_EINVALIDPATH;
if ((error = git_buf_sets(&buffer, directory_path)) < GIT_SUCCESS)
return error;
data.filename = filename;
data.filename_len = strlen(filename);
error = remove_placeholders_recurs(&data, &buffer);
git_buf_free(&buffer);
return error;
}
/*
* 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.
*/
#ifndef INCLUDE_test_helpers_h__
#define INCLUDE_test_helpers_h__
#include "test_lib.h"
#include <git2.h>
#include "odb.h"
#define TEST_REPOSITORY_NAME "testrepo.git"
#define REPOSITORY_FOLDER TEST_RESOURCES "/" TEST_REPOSITORY_NAME "/"
#define ODB_FOLDER (REPOSITORY_FOLDER "objects/")
#define TEST_INDEX_PATH (REPOSITORY_FOLDER "index")
#define TEST_INDEX2_PATH (TEST_RESOURCES "/gitgit.index")
#define TEST_INDEXBIG_PATH (TEST_RESOURCES "/big.index")
#define EMPTY_REPOSITORY_FOLDER TEST_RESOURCES "/empty_standard_repo/.gitted/"
#define TEMP_FOLDER ""
#define TEMP_REPO_FOLDER TEMP_FOLDER TEST_REPOSITORY_NAME "/"
#define TEMP_REPO_FOLDER_NS TEMP_FOLDER TEST_REPOSITORY_NAME
#define TEST_STD_REPO_FOLDER TEMP_REPO_FOLDER ".git/"
typedef struct object_data {
unsigned char *bytes; /* (compressed) bytes stored in object store */
size_t blen; /* length of data in object store */
char *id; /* object id (sha1) */
char *type; /* object type */
char *dir; /* object store (fan-out) directory name */
char *file; /* object store filename */
unsigned char *data; /* (uncompressed) object data */
size_t dlen; /* length of (uncompressed) object data */
} object_data;
extern int write_object_data(char *file, void *data, size_t len);
extern int write_object_files(const char *odb_dir, object_data *d);
extern int remove_object_files(const char *odb_dir, object_data *d);
extern int cmp_objects(git_rawobj *o, object_data *d);
extern void locate_loose_object(const char *odb_dir, git_object *object, char **out, char **out_folder);
extern int loose_object_mode(const char *odb_dir, git_object *object);
extern int loose_object_dir_mode(const char *odb_dir, git_object *object);
extern int remove_loose_object(const char *odb_dir, git_object *object);
extern int cmp_files(const char *a, const char *b);
extern int copy_file(const char *source, const char *dest);
extern int rmdir_recurs(const char *directory_path);
extern int copydir_recurs(const char *source_directory_path, const char *destination_directory_path);
extern int remove_placeholders(const char *directory_path, const char *filename);
extern int open_temp_repo(git_repository **repo, const char *path);
extern void close_temp_repo(git_repository *repo);
#endif
/* INCLUDE_test_helpers_h__ */
#include <assert.h>
#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "test_lib.h"
#define DO_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE)))
#define GIT_MAX_TEST_CASES 64
struct git_test {
char *name;
char *message;
char *failed_pos;
char *description;
char *error_message;
git_testfunc function;
unsigned failed:1, ran:1;
jmp_buf *jump;
};
struct git_testsuite {
char *name;
int count, fail_count;
git_test *list[GIT_MAX_TEST_CASES];
};
static void test_free(git_test *t)
{
if (t) {
free(t->name);
free(t->description);
free(t->failed_pos);
free(t->message);
free(t->error_message);
free(t);
}
}
static void test_run(git_test *tc)
{
jmp_buf buf;
tc->jump = &buf;
if (setjmp(buf) == 0) {
tc->ran = 1;
(tc->function)(tc);
}
tc->jump = 0;
}
static git_test *create_test(git_testfunc function)
{
git_test *t = DO_ALLOC(git_test);
memset(t, 0x0, sizeof(git_test));
t->function = function;
return t;
}
void git_test__init(git_test *t, const char *name, const char *description)
{
t->name = strdup(name);
t->description = strdup(description);
}
/*-------------------------------------------------------------------------*
* Public assert methods
*-------------------------------------------------------------------------*/
static void fail_test(git_test *tc, const char *file, int line, const char *message)
{
char buf[1024];
const char *last_error = git_lasterror();
snprintf(buf, 1024, "%s:%d", file, line);
tc->failed = 1;
tc->message = strdup(message);
tc->failed_pos = strdup(buf);
if (last_error)
tc->error_message = strdup(last_error);
if (tc->jump != 0)
longjmp(*(tc->jump), 0);
}
void git_test__fail(git_test *tc, const char *file, int line, const char *message)
{
fail_test(tc, file, line, message);
}
void git_test__assert(git_test *tc, const char *file, int line, const char *message, int condition)
{
if (condition == 0)
fail_test(tc, file, line, message);
}
void git_test__assert_pass(git_test *tc, const char *file, int line, const char *message, int ret_value)
{
if (ret_value < 0)
fail_test(tc, file, line, message);
}
/*-------------------------------------------------------------------------*
* Test Suite
*-------------------------------------------------------------------------*/
static void testsuite_init(git_testsuite *ts)
{
ts->count = 0;
ts->fail_count = 0;
memset(ts->list, 0, sizeof(ts->list));
}
git_testsuite *git_testsuite_new(const char *name)
{
git_testsuite *ts = DO_ALLOC(git_testsuite);
testsuite_init(ts);
ts->name = strdup(name);
return ts;
}
static void free_suite(git_testsuite *ts)
{
unsigned int n;
for (n = 0; n < GIT_MAX_TEST_CASES; n++)
if (ts->list[n])
test_free(ts->list[n]);
free(ts->name);
free(ts);
}
void git_testsuite_add(git_testsuite *ts, git_testfunc test)
{
assert(ts->count < GIT_MAX_TEST_CASES);
ts->list[ts->count++] = create_test(test);
}
static void print_details(git_testsuite *ts)
{
int i;
int failCount = 0;
if (ts->fail_count == 0) {
const char *testWord = ts->count == 1 ? "test" : "tests";
printf("OK (%d %s)\n", ts->count, testWord);
} else {
printf("Failed (%d failures):\n", ts->fail_count);
for (i = 0 ; i < ts->count ; ++i) {
git_test *tc = ts->list[i];
if (tc->failed) {
failCount++;
printf(" %d) \"%s\" [test %s @ %s]\n\t%s\n",
failCount, tc->description, tc->name, tc->failed_pos, tc->message);
if (tc->error_message)
printf("\tError: %s\n", tc->error_message);
}
}
}
}
int git_testsuite_run(git_testsuite *ts)
{
int i, fail_count;
printf("Suite \"%s\": ", ts->name);
for (i = 0 ; i < ts->count ; ++i) {
git_test *tc = ts->list[i];
test_run(tc);
if (tc->failed) {
ts->fail_count++;
putchar('F');
} else
putchar('.');
fflush(stdout);
}
printf("\n ");
print_details(ts);
fail_count = ts->fail_count;
free_suite(ts);
return fail_count;
}
#ifndef __LIBGIT2_TEST_H__
#define __LIBGIT2_TEST_H__
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include <git2.h>
#define DECLARE_SUITE(SNAME) extern git_testsuite *libgit2_suite_##SNAME(void)
#define SUITE_NAME(SNAME) libgit2_suite_##SNAME
#define BEGIN_SUITE(SNAME) \
git_testsuite *libgit2_suite_##SNAME(void);\
git_testsuite *libgit2_suite_##SNAME(void) {\
git_testsuite *_gitsuite = git_testsuite_new(#SNAME);
#define ADD_TEST(TNAME) \
git_testsuite_add(_gitsuite, _gittest__##TNAME);
#define END_SUITE \
return _gitsuite;\
}
#define BEGIN_TEST(TNAME, DESC) \
static void _gittest__##TNAME(git_test *_gittest) { \
git_test__init(_gittest, #TNAME, DESC); \
git_clearerror();\
{\
#define END_TEST }}
typedef struct git_test git_test;
typedef struct git_testsuite git_testsuite;
typedef void (*git_testfunc)(git_test *);
typedef git_testsuite *(*libgit2_suite)(void);
void git_test__init(git_test *t, const char *name, const char *description);
void git_test__fail(git_test *tc, const char *file, int line, const char *message);
void git_test__assert(git_test *tc, const char *file, int line, const char *message, int condition);
void git_test__assert_pass(git_test *tc, const char *file, int line, const char *message, int ret_value);
#define must_pass(expr) git_test__assert_pass(_gittest, __FILE__, __LINE__, "Method failed: " #expr, (expr))
#define must_fail(expr) git_test__assert(_gittest, __FILE__, __LINE__, "Expected method to fail: " #expr, (expr) < 0)
#define must_be_true(expr) git_test__assert(_gittest, __FILE__, __LINE__, "Expression is not true: " #expr, !!(expr))
git_testsuite *git_testsuite_new(const char *name);
void git_testsuite_add(git_testsuite *ts, git_testfunc test);
int git_testsuite_run(git_testsuite *ts);
#endif
/*
* 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 <string.h>
#include <git2.h>
#include "posix.h"
#include "test_lib.h"
#include "test_helpers.h"
DECLARE_SUITE(core);
DECLARE_SUITE(rawobjects);
DECLARE_SUITE(objwrite);
DECLARE_SUITE(commit);
DECLARE_SUITE(revwalk);
DECLARE_SUITE(index);
DECLARE_SUITE(hashtable);
DECLARE_SUITE(tag);
DECLARE_SUITE(tree);
DECLARE_SUITE(refs);
DECLARE_SUITE(repository);
DECLARE_SUITE(threads);
DECLARE_SUITE(buffers);
DECLARE_SUITE(status);
static libgit2_suite suite_methods[]= {
SUITE_NAME(core),
SUITE_NAME(rawobjects),
SUITE_NAME(objwrite),
SUITE_NAME(commit),
SUITE_NAME(revwalk),
SUITE_NAME(index),
SUITE_NAME(hashtable),
SUITE_NAME(tag),
SUITE_NAME(tree),
SUITE_NAME(refs),
SUITE_NAME(repository),
SUITE_NAME(threads),
SUITE_NAME(buffers),
SUITE_NAME(status),
};
#define GIT_SUITE_COUNT (ARRAY_SIZE(suite_methods))
#ifdef GIT_WIN32
int __cdecl
#else
int
#endif
main(int argc, char *argv[])
{
unsigned int i, failures;
GIT_UNUSED(argc);
GIT_UNUSED(argv);
git_threads_init();
p_umask(0);
failures = 0;
for (i = 0; i < GIT_SUITE_COUNT; ++i)
failures += git_testsuite_run(suite_methods[i]());
git_threads_shutdown();
return failures ? -1 : 0;
}
{
ignore-zlib-cond
Memcheck:Cond
obj:*libz.so*
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment