mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 06:51:09 +00:00
Find pack files in $GIT_DIR/objects/pack directory on git_odb_open
Currently we only catalog the available pack files into a table, storing their path names relative to the pack directory. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
7350e6337a
commit
b438016ecd
125
src/odb.c
125
src/odb.c
@ -30,14 +30,26 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define GIT_PACK_NAME_MAX (5 + 40 + 1)
|
||||||
|
typedef struct {
|
||||||
|
git_refcnt ref;
|
||||||
|
|
||||||
|
char pack_name[GIT_PACK_NAME_MAX];
|
||||||
|
} git_pack;
|
||||||
|
|
||||||
struct git_odb {
|
struct git_odb {
|
||||||
git_lck lock;
|
git_lck lock;
|
||||||
|
|
||||||
/** Path to the "objects" directory. */
|
/** Path to the "objects" directory. */
|
||||||
char *objects_dir;
|
char *objects_dir;
|
||||||
|
|
||||||
|
/** Known pack files from ${objects_dir}/packs. */
|
||||||
|
git_pack **packs;
|
||||||
|
size_t n_packs;
|
||||||
|
|
||||||
/** Alternate databases to search. */
|
/** Alternate databases to search. */
|
||||||
git_odb **alternates;
|
git_odb **alternates;
|
||||||
|
size_t n_alternates;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct { /* object header data */
|
typedef struct { /* object header data */
|
||||||
@ -432,13 +444,111 @@ static int open_alternates(git_odb *db)
|
|||||||
}
|
}
|
||||||
|
|
||||||
db->alternates[n] = NULL;
|
db->alternates[n] = NULL;
|
||||||
|
db->n_alternates = n;
|
||||||
gitlck_unlock(&db->lock);
|
gitlck_unlock(&db->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_pack(git_pack *p)
|
||||||
|
{
|
||||||
|
gitrc_free(&p->ref);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static git_pack *alloc_pack(const char *pack_name)
|
||||||
|
{
|
||||||
|
git_pack *p = git__calloc(1, sizeof(*p));
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
gitrc_init(&p->ref);
|
||||||
|
strcpy(p->pack_name, pack_name);
|
||||||
|
gitrc_inc(&p->ref);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct scanned_pack {
|
||||||
|
struct scanned_pack *next;
|
||||||
|
git_pack *pack;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int scan_one_pack(void *state, char *name)
|
||||||
|
{
|
||||||
|
struct scanned_pack **ret = state, *r;
|
||||||
|
char *s = strrchr(name, '/'), *d;
|
||||||
|
|
||||||
|
if (git__prefixcmp(s + 1, "pack-")
|
||||||
|
|| git__suffixcmp(s, ".pack")
|
||||||
|
|| strlen(s + 1) != GIT_PACK_NAME_MAX + 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
d = strrchr(s + 1, '.');
|
||||||
|
strcpy(d + 1, "idx"); /* "pack-abc.pack" -> "pack-abc.idx" */
|
||||||
|
if (gitfo_exists(name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(r = git__malloc(sizeof(*r))))
|
||||||
|
return GIT_ERROR;
|
||||||
|
|
||||||
|
*d = '\0'; /* "pack-abc.pack" -_> "pack-abc" */
|
||||||
|
if (!(r->pack = alloc_pack(s + 1))) {
|
||||||
|
free(r);
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->next = *ret;
|
||||||
|
*ret = r;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scan_packs(git_odb *db)
|
||||||
|
{
|
||||||
|
char pb[GIT_PATH_MAX];
|
||||||
|
struct scanned_pack *state = NULL, *c;
|
||||||
|
size_t cnt;
|
||||||
|
|
||||||
|
if (git__fmt(pb, sizeof(pb), "%s/pack", db->objects_dir) < 0)
|
||||||
|
return GIT_ERROR;
|
||||||
|
gitfo_dirent(pb, sizeof(pb), scan_one_pack, &state);
|
||||||
|
gitlck_lock(&db->lock);
|
||||||
|
|
||||||
|
if (!db->packs) {
|
||||||
|
for (cnt = 0, c = state; c; c = c->next)
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
db->packs = git__malloc(sizeof(*db->packs) * (cnt + 1));
|
||||||
|
if (!db->packs)
|
||||||
|
goto unlock_fail;
|
||||||
|
for (cnt = 0, c = state; c; ) {
|
||||||
|
struct scanned_pack *n = c->next;
|
||||||
|
db->packs[cnt++] = c->pack;
|
||||||
|
free(c);
|
||||||
|
c = n;
|
||||||
|
}
|
||||||
|
db->packs[cnt] = NULL;
|
||||||
|
db->n_packs = cnt;
|
||||||
|
} else {
|
||||||
|
/* TODO - merge new entries into the existing array */
|
||||||
|
goto unlock_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
gitlck_unlock(&db->lock);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unlock_fail:
|
||||||
|
gitlck_unlock(&db->lock);
|
||||||
|
while (state) {
|
||||||
|
struct scanned_pack *n = state->next;
|
||||||
|
free_pack(state->pack);
|
||||||
|
free(state);
|
||||||
|
state = n;
|
||||||
|
}
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
int git_odb_open(git_odb **out, const char *objects_dir)
|
int git_odb_open(git_odb **out, const char *objects_dir)
|
||||||
{
|
{
|
||||||
git_odb *db = git__malloc(sizeof(*db));
|
git_odb *db = git__calloc(1, sizeof(*db));
|
||||||
if (!db)
|
if (!db)
|
||||||
return GIT_ERROR;
|
return GIT_ERROR;
|
||||||
|
|
||||||
@ -448,8 +558,11 @@ int git_odb_open(git_odb **out, const char *objects_dir)
|
|||||||
return GIT_ERROR;
|
return GIT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
db->alternates = NULL;
|
|
||||||
gitlck_init(&db->lock);
|
gitlck_init(&db->lock);
|
||||||
|
if (scan_packs(db)) {
|
||||||
|
git_odb_close(db);
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
*out = db;
|
*out = db;
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
@ -462,6 +575,14 @@ void git_odb_close(git_odb *db)
|
|||||||
|
|
||||||
gitlck_lock(&db->lock);
|
gitlck_lock(&db->lock);
|
||||||
|
|
||||||
|
if (db->packs) {
|
||||||
|
git_pack **p;
|
||||||
|
for (p = db->packs; *p; p++)
|
||||||
|
if (gitrc_dec(&(*p)->ref))
|
||||||
|
free_pack(*p);
|
||||||
|
free(db->packs);
|
||||||
|
}
|
||||||
|
|
||||||
if (db->alternates) {
|
if (db->alternates) {
|
||||||
git_odb **alt;
|
git_odb **alt;
|
||||||
for (alt = db->alternates; *alt; alt++)
|
for (alt = db->alternates; *alt; alt++)
|
||||||
|
Loading…
Reference in New Issue
Block a user