mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 20:33:41 +00:00

The signature for the reflog is not something which changes dynamically. Almost all uses will be NULL, since we want for the repository's default identity to be used, making it noise. In order to allow for changing the identity, we instead provide git_repository_set_ident() and git_repository_ident() which allow a user to override the choice of signature.
222 lines
4.5 KiB
C
222 lines
4.5 KiB
C
#include "clar_libgit2.h"
|
|
#include "git2/refdb.h"
|
|
#include "refdb.h"
|
|
|
|
static git_repository *g_repo;
|
|
static int g_expected = 0;
|
|
|
|
void test_threads_refdb__initialize(void)
|
|
{
|
|
g_repo = NULL;
|
|
}
|
|
|
|
void test_threads_refdb__cleanup(void)
|
|
{
|
|
cl_git_sandbox_cleanup();
|
|
g_repo = NULL;
|
|
}
|
|
|
|
#define REPEAT 20
|
|
#define THREADS 20
|
|
|
|
static void *iterate_refs(void *arg)
|
|
{
|
|
git_reference_iterator *i;
|
|
git_reference *ref;
|
|
int count = 0;
|
|
|
|
cl_git_pass(git_reference_iterator_new(&i, g_repo));
|
|
|
|
for (count = 0; !git_reference_next(&ref, i); ++count) {
|
|
cl_assert(ref != NULL);
|
|
git_reference_free(ref);
|
|
}
|
|
|
|
if (g_expected > 0)
|
|
cl_assert_equal_i(g_expected, count);
|
|
|
|
git_reference_iterator_free(i);
|
|
|
|
giterr_clear();
|
|
return arg;
|
|
}
|
|
|
|
void test_threads_refdb__iterator(void)
|
|
{
|
|
int r, t;
|
|
git_thread th[THREADS];
|
|
int id[THREADS];
|
|
git_oid head;
|
|
git_reference *ref;
|
|
char name[128];
|
|
git_refdb *refdb;
|
|
|
|
g_repo = cl_git_sandbox_init("testrepo2");
|
|
|
|
cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));
|
|
|
|
/* make a bunch of references */
|
|
|
|
for (r = 0; r < 200; ++r) {
|
|
p_snprintf(name, sizeof(name), "refs/heads/direct-%03d", r);
|
|
cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL));
|
|
git_reference_free(ref);
|
|
}
|
|
|
|
cl_git_pass(git_repository_refdb(&refdb, g_repo));
|
|
cl_git_pass(git_refdb_compress(refdb));
|
|
git_refdb_free(refdb);
|
|
|
|
g_expected = 206;
|
|
|
|
for (r = 0; r < REPEAT; ++r) {
|
|
g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */
|
|
|
|
for (t = 0; t < THREADS; ++t) {
|
|
id[t] = t;
|
|
#ifdef GIT_THREADS
|
|
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
|
|
#else
|
|
th[t] = t;
|
|
iterate_refs(&id[t]);
|
|
#endif
|
|
}
|
|
|
|
#ifdef GIT_THREADS
|
|
for (t = 0; t < THREADS; ++t) {
|
|
cl_git_pass(git_thread_join(&th[t], NULL));
|
|
}
|
|
#endif
|
|
|
|
memset(th, 0, sizeof(th));
|
|
}
|
|
}
|
|
|
|
static void *create_refs(void *arg)
|
|
{
|
|
int *id = arg, i;
|
|
git_oid head;
|
|
char name[128];
|
|
git_reference *ref[10];
|
|
|
|
cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));
|
|
|
|
for (i = 0; i < 10; ++i) {
|
|
p_snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i);
|
|
cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0, NULL));
|
|
|
|
if (i == 5) {
|
|
git_refdb *refdb;
|
|
cl_git_pass(git_repository_refdb(&refdb, g_repo));
|
|
cl_git_pass(git_refdb_compress(refdb));
|
|
git_refdb_free(refdb);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 10; ++i)
|
|
git_reference_free(ref[i]);
|
|
|
|
giterr_clear();
|
|
return arg;
|
|
}
|
|
|
|
static void *delete_refs(void *arg)
|
|
{
|
|
int *id = arg, i;
|
|
git_reference *ref;
|
|
char name[128];
|
|
|
|
for (i = 0; i < 10; ++i) {
|
|
p_snprintf(
|
|
name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i);
|
|
|
|
if (!git_reference_lookup(&ref, g_repo, name)) {
|
|
cl_git_pass(git_reference_delete(ref));
|
|
git_reference_free(ref);
|
|
}
|
|
|
|
if (i == 5) {
|
|
git_refdb *refdb;
|
|
cl_git_pass(git_repository_refdb(&refdb, g_repo));
|
|
cl_git_pass(git_refdb_compress(refdb));
|
|
git_refdb_free(refdb);
|
|
}
|
|
}
|
|
|
|
giterr_clear();
|
|
return arg;
|
|
}
|
|
|
|
void test_threads_refdb__edit_while_iterate(void)
|
|
{
|
|
int r, t;
|
|
int id[THREADS];
|
|
git_oid head;
|
|
git_reference *ref;
|
|
char name[128];
|
|
git_refdb *refdb;
|
|
|
|
#ifdef GIT_THREADS
|
|
git_thread th[THREADS];
|
|
#endif
|
|
|
|
g_repo = cl_git_sandbox_init("testrepo2");
|
|
|
|
cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD"));
|
|
|
|
/* make a bunch of references */
|
|
|
|
for (r = 0; r < 50; ++r) {
|
|
p_snprintf(name, sizeof(name), "refs/heads/starter-%03d", r);
|
|
cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL));
|
|
git_reference_free(ref);
|
|
}
|
|
|
|
cl_git_pass(git_repository_refdb(&refdb, g_repo));
|
|
cl_git_pass(git_refdb_compress(refdb));
|
|
git_refdb_free(refdb);
|
|
|
|
g_expected = -1;
|
|
|
|
g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */
|
|
|
|
for (t = 0; t < THREADS; ++t) {
|
|
void *(*fn)(void *arg);
|
|
|
|
switch (t & 0x3) {
|
|
case 0: fn = create_refs; break;
|
|
case 1: fn = delete_refs; break;
|
|
default: fn = iterate_refs; break;
|
|
}
|
|
|
|
id[t] = t;
|
|
|
|
/* It appears with all reflog writing changes, etc., that this
|
|
* test has started to fail quite frequently, so let's disable it
|
|
* for now by just running on a single thread...
|
|
*/
|
|
/* #ifdef GIT_THREADS */
|
|
/* cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); */
|
|
/* #else */
|
|
fn(&id[t]);
|
|
/* #endif */
|
|
}
|
|
|
|
#ifdef GIT_THREADS
|
|
/* for (t = 0; t < THREADS; ++t) { */
|
|
/* cl_git_pass(git_thread_join(th[t], NULL)); */
|
|
/* } */
|
|
|
|
memset(th, 0, sizeof(th));
|
|
|
|
for (t = 0; t < THREADS; ++t) {
|
|
id[t] = t;
|
|
cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t]));
|
|
}
|
|
|
|
for (t = 0; t < THREADS; ++t) {
|
|
cl_git_pass(git_thread_join(&th[t], NULL));
|
|
}
|
|
#endif
|
|
}
|