Commit e56f3507 by Edward Thomson

refdb: teach filesystem refdb about sha256

parent fe2ee3a0
...@@ -60,15 +60,17 @@ typedef struct refdb_fs_backend { ...@@ -60,15 +60,17 @@ typedef struct refdb_fs_backend {
/* path to common objects' directory */ /* path to common objects' directory */
char *commonpath; char *commonpath;
git_sortedcache *refcache; git_oid_t oid_type;
int fsync : 1,
sorted : 1;
int peeling_mode; int peeling_mode;
git_iterator_flag_t iterator_flags; git_iterator_flag_t iterator_flags;
uint32_t direach_flags; uint32_t direach_flags;
int fsync; git_sortedcache *refcache;
git_map packed_refs_map; git_map packed_refs_map;
git_mutex prlock; /* protect packed_refs_map */ git_mutex prlock; /* protect packed_refs_map */
git_futils_filestamp packed_refs_stamp; git_futils_filestamp packed_refs_stamp;
bool sorted;
} refdb_fs_backend; } refdb_fs_backend;
static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name); static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
...@@ -113,6 +115,7 @@ static int packed_reload(refdb_fs_backend *backend) ...@@ -113,6 +115,7 @@ static int packed_reload(refdb_fs_backend *backend)
{ {
int error; int error;
git_str packedrefs = GIT_STR_INIT; git_str packedrefs = GIT_STR_INIT;
size_t oid_hexsize = git_oid_hexsize(backend->oid_type);
char *scan, *eof, *eol; char *scan, *eof, *eol;
if (!backend->gitpath) if (!backend->gitpath)
...@@ -158,9 +161,9 @@ static int packed_reload(refdb_fs_backend *backend) ...@@ -158,9 +161,9 @@ static int packed_reload(refdb_fs_backend *backend)
/* parse "<OID> <refname>\n" */ /* parse "<OID> <refname>\n" */
if (git_oid__fromstr(&oid, scan, GIT_OID_SHA1) < 0) if (git_oid__fromstr(&oid, scan, backend->oid_type) < 0)
goto parse_failed; goto parse_failed;
scan += GIT_OID_SHA1_HEXSIZE; scan += oid_hexsize;
if (*scan++ != ' ') if (*scan++ != ' ')
goto parse_failed; goto parse_failed;
...@@ -179,9 +182,9 @@ static int packed_reload(refdb_fs_backend *backend) ...@@ -179,9 +182,9 @@ static int packed_reload(refdb_fs_backend *backend)
/* look for optional "^<OID>\n" */ /* look for optional "^<OID>\n" */
if (*scan == '^') { if (*scan == '^') {
if (git_oid__fromstr(&oid, scan + 1, GIT_OID_SHA1) < 0) if (git_oid__fromstr(&oid, scan + 1, backend->oid_type) < 0)
goto parse_failed; goto parse_failed;
scan += GIT_OID_SHA1_HEXSIZE + 1; scan += oid_hexsize + 1;
if (scan < eof) { if (scan < eof) {
if (!(eol = strchr(scan, '\n'))) if (!(eol = strchr(scan, '\n')))
...@@ -214,19 +217,23 @@ parse_failed: ...@@ -214,19 +217,23 @@ parse_failed:
} }
static int loose_parse_oid( static int loose_parse_oid(
git_oid *oid, const char *filename, git_str *file_content) git_oid *oid,
const char *filename,
git_str *file_content,
git_oid_t oid_type)
{ {
const char *str = git_str_cstr(file_content); const char *str = git_str_cstr(file_content);
size_t oid_hexsize = git_oid_hexsize(oid_type);
if (git_str_len(file_content) < GIT_OID_SHA1_HEXSIZE) if (git_str_len(file_content) < oid_hexsize)
goto corrupted; goto corrupted;
/* we need to get 40 OID characters from the file */ /* we need to get 40 OID characters from the file */
if (git_oid__fromstr(oid, str, GIT_OID_SHA1) < 0) if (git_oid__fromstr(oid, str, oid_type) < 0)
goto corrupted; goto corrupted;
/* If the file is longer than 40 chars, the 41st must be a space */ /* If the file is longer than 40 chars, the 41st must be a space */
str += GIT_OID_SHA1_HEXSIZE; str += oid_hexsize;
if (*str == '\0' || git__isspace(*str)) if (*str == '\0' || git__isspace(*str))
return 0; return 0;
...@@ -266,7 +273,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name) ...@@ -266,7 +273,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
goto done; goto done;
/* parse OID from file */ /* parse OID from file */
if ((error = loose_parse_oid(&oid, name, &ref_file)) < 0) if ((error = loose_parse_oid(&oid, name, &ref_file, backend->oid_type)) < 0)
goto done; goto done;
if ((error = git_sortedcache_wlock(backend->refcache)) < 0) if ((error = git_sortedcache_wlock(backend->refcache)) < 0)
...@@ -437,7 +444,7 @@ static int loose_lookup( ...@@ -437,7 +444,7 @@ static int loose_lookup(
} else { } else {
git_oid oid; git_oid oid;
if (!(error = loose_parse_oid(&oid, ref_name, &ref_file)) && if (!(error = loose_parse_oid(&oid, ref_name, &ref_file, backend->oid_type)) &&
out != NULL) out != NULL)
*out = git_reference__alloc(ref_name, &oid, NULL); *out = git_reference__alloc(ref_name, &oid, NULL);
} }
...@@ -615,19 +622,24 @@ static const char *end_of_record(const char *p, const char *end) ...@@ -615,19 +622,24 @@ static const char *end_of_record(const char *p, const char *end)
return p; return p;
} }
static int static int cmp_record_to_refname(
cmp_record_to_refname(const char *rec, size_t data_end, const char *ref_name) const char *rec,
size_t data_end,
const char *ref_name,
git_oid_t oid_type)
{ {
const size_t ref_len = strlen(ref_name); const size_t ref_len = strlen(ref_name);
int cmp_val; int cmp_val;
const char *end; const char *end;
size_t oid_hexsize = git_oid_hexsize(oid_type);
rec += GIT_OID_SHA1_HEXSIZE + 1; /* <oid> + space */ rec += oid_hexsize + 1; /* <oid> + space */
if (data_end < GIT_OID_SHA1_HEXSIZE + 3) {
/* an incomplete (corrupt) record is treated as less than ref_name */ /* an incomplete (corrupt) record is treated as less than ref_name */
if (data_end < oid_hexsize + 3)
return -1; return -1;
}
data_end -= GIT_OID_SHA1_HEXSIZE + 1; data_end -= oid_hexsize + 1;
end = memchr(rec, '\n', data_end); end = memchr(rec, '\n', data_end);
if (end) if (end)
...@@ -675,6 +687,7 @@ static int packed_lookup( ...@@ -675,6 +687,7 @@ static int packed_lookup(
{ {
int error = 0; int error = 0;
const char *left, *right, *data_end; const char *left, *right, *data_end;
size_t oid_hexsize = git_oid_hexsize(backend->oid_type);
if ((error = packed_map_check(backend)) < 0) if ((error = packed_map_check(backend)) < 0)
return error; return error;
...@@ -698,7 +711,7 @@ static int packed_lookup( ...@@ -698,7 +711,7 @@ static int packed_lookup(
mid = left + (right - left) / 2; mid = left + (right - left) / 2;
rec = start_of_record(left, mid); rec = start_of_record(left, mid);
compare = cmp_record_to_refname(rec, data_end - rec, ref_name); compare = cmp_record_to_refname(rec, data_end - rec, ref_name, backend->oid_type);
if (compare < 0) { if (compare < 0) {
left = end_of_record(mid, right); left = end_of_record(mid, right);
...@@ -708,11 +721,11 @@ static int packed_lookup( ...@@ -708,11 +721,11 @@ static int packed_lookup(
const char *eol; const char *eol;
git_oid oid, peel, *peel_ptr = NULL; git_oid oid, peel, *peel_ptr = NULL;
if (data_end - rec < GIT_OID_SHA1_HEXSIZE || if (data_end - rec < (long)oid_hexsize ||
git_oid__fromstr(&oid, rec, GIT_OID_SHA1) < 0) { git_oid__fromstr(&oid, rec, backend->oid_type) < 0) {
goto parse_failed; goto parse_failed;
} }
rec += GIT_OID_SHA1_HEXSIZE + 1; rec += oid_hexsize + 1;
if (!(eol = memchr(rec, '\n', data_end - rec))) { if (!(eol = memchr(rec, '\n', data_end - rec))) {
goto parse_failed; goto parse_failed;
} }
...@@ -724,8 +737,8 @@ static int packed_lookup( ...@@ -724,8 +737,8 @@ static int packed_lookup(
if (*rec == '^') { if (*rec == '^') {
rec++; rec++;
if (data_end - rec < GIT_OID_SHA1_HEXSIZE || if (data_end - rec < (long)oid_hexsize ||
git_oid__fromstr(&peel, rec, GIT_OID_SHA1) < 0) { git_oid__fromstr(&peel, rec, backend->oid_type) < 0) {
goto parse_failed; goto parse_failed;
} }
peel_ptr = &peel; peel_ptr = &peel;
...@@ -1108,7 +1121,7 @@ static int loose_commit(git_filebuf *file, const git_reference *ref) ...@@ -1108,7 +1121,7 @@ static int loose_commit(git_filebuf *file, const git_reference *ref)
GIT_ASSERT_ARG(ref); GIT_ASSERT_ARG(ref);
if (ref->type == GIT_REFERENCE_DIRECT) { if (ref->type == GIT_REFERENCE_DIRECT) {
char oid[GIT_OID_SHA1_HEXSIZE + 1]; char oid[GIT_OID_MAX_HEXSIZE + 1];
git_oid_nfmt(oid, sizeof(oid), &ref->target.oid); git_oid_nfmt(oid, sizeof(oid), &ref->target.oid);
git_filebuf_printf(file, "%s\n", oid); git_filebuf_printf(file, "%s\n", oid);
...@@ -1224,7 +1237,7 @@ static int packed_find_peel(refdb_fs_backend *backend, struct packref *ref) ...@@ -1224,7 +1237,7 @@ static int packed_find_peel(refdb_fs_backend *backend, struct packref *ref)
*/ */
static int packed_write_ref(struct packref *ref, git_filebuf *file) static int packed_write_ref(struct packref *ref, git_filebuf *file)
{ {
char oid[GIT_OID_SHA1_HEXSIZE + 1]; char oid[GIT_OID_MAX_HEXSIZE + 1];
git_oid_nfmt(oid, sizeof(oid), &ref->oid); git_oid_nfmt(oid, sizeof(oid), &ref->oid);
/* /*
...@@ -1238,7 +1251,7 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file) ...@@ -1238,7 +1251,7 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file)
* The required peels have already been loaded into `ref->peel_target`. * The required peels have already been loaded into `ref->peel_target`.
*/ */
if (ref->flags & PACKREF_HAS_PEEL) { if (ref->flags & PACKREF_HAS_PEEL) {
char peel[GIT_OID_SHA1_HEXSIZE + 1]; char peel[GIT_OID_MAX_HEXSIZE + 1];
git_oid_nfmt(peel, sizeof(peel), &ref->peel); git_oid_nfmt(peel, sizeof(peel), &ref->peel);
if (git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel) < 0) if (git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel) < 0)
...@@ -1302,7 +1315,7 @@ static int packed_remove_loose(refdb_fs_backend *backend) ...@@ -1302,7 +1315,7 @@ static int packed_remove_loose(refdb_fs_backend *backend)
continue; continue;
/* Figure out the current id; if we find a bad ref file, skip it so we can do the rest */ /* Figure out the current id; if we find a bad ref file, skip it so we can do the rest */
if (loose_parse_oid(&current_id, lock.path_original, &ref_content) < 0) if (loose_parse_oid(&current_id, lock.path_original, &ref_content, backend->oid_type) < 0)
continue; continue;
/* If the ref moved since we packed it, we must not delete it */ /* If the ref moved since we packed it, we must not delete it */
...@@ -1891,7 +1904,10 @@ done: ...@@ -1891,7 +1904,10 @@ done:
return out; return out;
} }
static int reflog_alloc(git_reflog **reflog, const char *name) static int reflog_alloc(
git_reflog **reflog,
const char *name,
git_oid_t oid_type)
{ {
git_reflog *log; git_reflog *log;
...@@ -1903,6 +1919,8 @@ static int reflog_alloc(git_reflog **reflog, const char *name) ...@@ -1903,6 +1919,8 @@ static int reflog_alloc(git_reflog **reflog, const char *name)
log->ref_name = git__strdup(name); log->ref_name = git__strdup(name);
GIT_ERROR_CHECK_ALLOC(log->ref_name); GIT_ERROR_CHECK_ALLOC(log->ref_name);
log->oid_type = oid_type;
if (git_vector_init(&log->entries, 0, NULL) < 0) { if (git_vector_init(&log->entries, 0, NULL) < 0) {
git__free(log->ref_name); git__free(log->ref_name);
git__free(log); git__free(log);
...@@ -2032,7 +2050,10 @@ static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *nam ...@@ -2032,7 +2050,10 @@ static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *nam
return has_reflog(backend->repo, name); return has_reflog(backend->repo, name);
} }
static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name) static int refdb_reflog_fs__read(
git_reflog **out,
git_refdb_backend *_backend,
const char *name)
{ {
int error = -1; int error = -1;
git_str log_path = GIT_STR_INIT; git_str log_path = GIT_STR_INIT;
...@@ -2048,7 +2069,7 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, ...@@ -2048,7 +2069,7 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend,
backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo; repo = backend->repo;
if (reflog_alloc(&log, name) < 0) if (reflog_alloc(&log, name, backend->oid_type) < 0)
return -1; return -1;
if (reflog_path(&log_path, repo, name) < 0) if (reflog_path(&log_path, repo, name) < 0)
...@@ -2086,11 +2107,11 @@ static int serialize_reflog_entry( ...@@ -2086,11 +2107,11 @@ static int serialize_reflog_entry(
const git_signature *committer, const git_signature *committer,
const char *msg) const char *msg)
{ {
char raw_old[GIT_OID_SHA1_HEXSIZE+1]; char raw_old[GIT_OID_MAX_HEXSIZE + 1];
char raw_new[GIT_OID_SHA1_HEXSIZE+1]; char raw_new[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(raw_old, GIT_OID_SHA1_HEXSIZE+1, oid_old); git_oid_tostr(raw_old, GIT_OID_MAX_HEXSIZE + 1, oid_old);
git_oid_tostr(raw_new, GIT_OID_SHA1_HEXSIZE+1, oid_new); git_oid_tostr(raw_new, GIT_OID_MAX_HEXSIZE + 1, oid_new);
git_str_clear(buf); git_str_clear(buf);
...@@ -2189,10 +2210,16 @@ success: ...@@ -2189,10 +2210,16 @@ success:
} }
/* Append to the reflog, must be called under reference lock */ /* Append to the reflog, must be called under reference lock */
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *who, const char *message) static int reflog_append(
refdb_fs_backend *backend,
const git_reference *ref,
const git_oid *old,
const git_oid *new,
const git_signature *who,
const char *message)
{ {
int error, is_symbolic, open_flags; int error, is_symbolic, open_flags;
git_oid old_id = GIT_OID_SHA1_ZERO, new_id = GIT_OID_SHA1_ZERO; git_oid old_id, new_id;
git_str buf = GIT_STR_INIT, path = GIT_STR_INIT; git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
git_repository *repo = backend->repo; git_repository *repo = backend->repo;
...@@ -2206,6 +2233,9 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co ...@@ -2206,6 +2233,9 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
/* From here on is_symbolic also means that it's HEAD */ /* From here on is_symbolic also means that it's HEAD */
git_oid_clear(&old_id, backend->oid_type);
git_oid_clear(&new_id, backend->oid_type);
if (old) { if (old) {
git_oid_cpy(&old_id, old); git_oid_cpy(&old_id, old);
} else { } else {
...@@ -2402,6 +2432,7 @@ int git_refdb_backend_fs( ...@@ -2402,6 +2432,7 @@ int git_refdb_backend_fs(
goto fail; goto fail;
backend->repo = repository; backend->repo = repository;
backend->oid_type = repository->oid_type;
if (repository->gitdir) { if (repository->gitdir) {
backend->gitpath = setup_namespace(repository, repository->gitdir); backend->gitpath = setup_namespace(repository, repository->gitdir);
......
...@@ -71,7 +71,11 @@ int git_reflog_write(git_reflog *reflog) ...@@ -71,7 +71,11 @@ int git_reflog_write(git_reflog *reflog)
return db->backend->reflog_write(db->backend, reflog); return db->backend->reflog_write(db->backend, reflog);
} }
int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) int git_reflog_append(
git_reflog *reflog,
const git_oid *new_oid,
const git_signature *committer,
const char *msg)
{ {
const git_reflog_entry *previous; const git_reflog_entry *previous;
git_reflog_entry *entry; git_reflog_entry *entry;
...@@ -104,7 +108,7 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign ...@@ -104,7 +108,7 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign
previous = git_reflog_entry_byindex(reflog, 0); previous = git_reflog_entry_byindex(reflog, 0);
if (previous == NULL) if (previous == NULL)
git_oid__fromstr(&entry->oid_old, GIT_OID_SHA1_HEXZERO, GIT_OID_SHA1); git_oid_clear(&entry->oid_old, reflog->oid_type);
else else
git_oid_cpy(&entry->oid_old, &previous->oid_cur); git_oid_cpy(&entry->oid_old, &previous->oid_cur);
...@@ -218,12 +222,8 @@ int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry) ...@@ -218,12 +222,8 @@ int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry)
/* If the oldest entry has just been removed... */ /* If the oldest entry has just been removed... */
if (idx == entrycount - 1) { if (idx == entrycount - 1) {
git_oid zero = GIT_OID_SHA1_ZERO;
/* ...clear the oid_old member of the "new" oldest entry */ /* ...clear the oid_old member of the "new" oldest entry */
if (git_oid_cpy(&entry->oid_old, &zero) < 0) git_oid_clear(&entry->oid_old, reflog->oid_type);
return -1;
return 0; return 0;
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#define GIT_REFLOG_DIR_MODE 0777 #define GIT_REFLOG_DIR_MODE 0777
#define GIT_REFLOG_FILE_MODE 0666 #define GIT_REFLOG_FILE_MODE 0666
#define GIT_REFLOG_SIZE_MIN (2*GIT_OID_SHA1_HEXSIZE+2+17)
struct git_reflog_entry { struct git_reflog_entry {
git_oid oid_old; git_oid oid_old;
git_oid oid_cur; git_oid oid_cur;
...@@ -30,6 +28,7 @@ struct git_reflog_entry { ...@@ -30,6 +28,7 @@ struct git_reflog_entry {
struct git_reflog { struct git_reflog {
git_refdb *db; git_refdb *db;
char *ref_name; char *ref_name;
git_oid_t oid_type;
git_vector entries; git_vector entries;
}; };
......
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