diff options
author | Vicent Marti <tanoku@gmail.com> | 2013-06-25 00:25:35 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2013-06-25 00:25:35 +0200 |
commit | 29d7242b1dcd1f09a63417abd648a6217b85d301 (patch) | |
tree | dedc3bc07a500770382ca4c517e4bb015e506c4b /src/refdb_fs.c | |
parent | a50086d174658914d4d6462afbc83b02825b1f5b (diff) | |
parent | eddc1f1ed78898a4ca41480045b1d0d5b075e773 (diff) | |
download | libgit2-29d7242b1dcd1f09a63417abd648a6217b85d301.tar.gz |
Merge branch 'development'
Diffstat (limited to 'src/refdb_fs.c')
-rw-r--r-- | src/refdb_fs.c | 520 |
1 files changed, 387 insertions, 133 deletions
diff --git a/src/refdb_fs.c b/src/refdb_fs.c index f00bd72a0..b9e283ac5 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -9,16 +9,18 @@ #include "hash.h" #include "repository.h" #include "fileops.h" +#include "filebuf.h" #include "pack.h" #include "reflog.h" -#include "config.h" #include "refdb.h" #include "refdb_fs.h" +#include "iterator.h" #include <git2/tag.h> #include <git2/object.h> #include <git2/refdb.h> -#include <git2/refdb_backend.h> +#include <git2/sys/refdb_backend.h> +#include <git2/sys/refs.h> GIT__USE_STRMAP; @@ -26,8 +28,16 @@ GIT__USE_STRMAP; #define MAX_NESTING_LEVEL 10 enum { - GIT_PACKREF_HAS_PEEL = 1, - GIT_PACKREF_WAS_LOOSE = 2 + PACKREF_HAS_PEEL = 1, + PACKREF_WAS_LOOSE = 2, + PACKREF_CANNOT_PEEL = 4, + PACKREF_SHADOWED = 8, +}; + +enum { + PEELING_NONE = 0, + PEELING_STANDARD, + PEELING_FULL }; struct packref { @@ -41,10 +51,10 @@ typedef struct refdb_fs_backend { git_refdb_backend parent; git_repository *repo; - const char *path; - git_refdb *refdb; + char *path; git_refcache refcache; + int peeling_mode; } refdb_fs_backend; static int reference_read( @@ -62,7 +72,7 @@ static int reference_read( /* Determine the full path of the file */ if (git_buf_joinpath(&path, repo_path, ref_name) < 0) return -1; - + result = git_futils_readbuffer_updated(file_content, path.ptr, mtime, NULL, updated); git_buf_free(&path); @@ -99,7 +109,7 @@ static int packed_parse_oid( refname_len = refname_end - refname_begin; - ref = git__malloc(sizeof(struct packref) + refname_len + 1); + ref = git__calloc(1, sizeof(struct packref) + refname_len + 1); GITERR_CHECK_ALLOC(ref); memcpy(ref->name, refname_begin, refname_len); @@ -107,11 +117,8 @@ static int packed_parse_oid( git_oid_cpy(&ref->oid, &id); - ref->flags = 0; - *ref_out = ref; *buffer_out = refname_end + 1; - return 0; corrupt: @@ -133,10 +140,6 @@ static int packed_parse_peel( if (tag_ref == NULL) goto corrupt; - /* Ensure reference is a tag */ - if (git__prefixcmp(tag_ref->name, GIT_REFS_TAGS_DIR) != 0) - goto corrupt; - if (buffer + GIT_OID_HEXSZ > buffer_end) goto corrupt; @@ -155,6 +158,7 @@ static int packed_parse_peel( goto corrupt; } + tag_ref->flags |= PACKREF_HAS_PEEL; *buffer_out = buffer; return 0; @@ -175,7 +179,10 @@ static int packed_load(refdb_fs_backend *backend) ref_cache->packfile = git_strmap_alloc(); GITERR_CHECK_ALLOC(ref_cache->packfile); } - + + if (backend->path == NULL) + return 0; + result = reference_read(&packfile, &ref_cache->packfile_time, backend->path, GIT_PACKEDREFS_FILE, &updated); @@ -193,7 +200,7 @@ static int packed_load(refdb_fs_backend *backend) if (result < 0) return -1; - + if (!updated) return 0; @@ -206,6 +213,30 @@ static int packed_load(refdb_fs_backend *backend) buffer_start = (const char *)packfile.ptr; buffer_end = (const char *)(buffer_start) + packfile.size; + backend->peeling_mode = PEELING_NONE; + + if (buffer_start[0] == '#') { + static const char *traits_header = "# pack-refs with: "; + + if (git__prefixcmp(buffer_start, traits_header) == 0) { + char *traits = (char *)buffer_start + strlen(traits_header); + char *traits_end = strchr(traits, '\n'); + + if (traits_end == NULL) + goto parse_failed; + + *traits_end = '\0'; + + if (strstr(traits, " fully-peeled ") != NULL) { + backend->peeling_mode = PEELING_FULL; + } else if (strstr(traits, " peeled ") != NULL) { + backend->peeling_mode = PEELING_STANDARD; + } + + buffer_start = traits_end + 1; + } + } + while (buffer_start < buffer_end && buffer_start[0] == '#') { buffer_start = strchr(buffer_start, '\n'); if (buffer_start == NULL) @@ -224,6 +255,10 @@ static int packed_load(refdb_fs_backend *backend) if (buffer_start[0] == '^') { if (packed_parse_peel(ref, &buffer_start, buffer_end) < 0) goto parse_failed; + } else if (backend->peeling_mode == PEELING_FULL || + (backend->peeling_mode == PEELING_STANDARD && + git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) == 0)) { + ref->flags |= PACKREF_CANNOT_PEEL; } git_strmap_insert(ref_cache->packfile, ref->name, ref, err); @@ -241,7 +276,7 @@ parse_failed: return -1; } -static int loose_parse_oid(git_oid *oid, git_buf *file_content) +static int loose_parse_oid(git_oid *oid, const char *filename, git_buf *file_content) { size_t len; const char *str; @@ -263,7 +298,7 @@ static int loose_parse_oid(git_oid *oid, git_buf *file_content) return 0; corrupted: - giterr_set(GITERR_REFERENCE, "Corrupted loose reference file"); + giterr_set(GITERR_REFERENCE, "Corrupted loose reference file: %s", filename); return -1; } @@ -284,19 +319,19 @@ static int loose_lookup_to_packfile( git_buf_rtrim(&ref_file); name_len = strlen(name); - ref = git__malloc(sizeof(struct packref) + name_len + 1); + ref = git__calloc(1, sizeof(struct packref) + name_len + 1); GITERR_CHECK_ALLOC(ref); memcpy(ref->name, name, name_len); ref->name[name_len] = 0; - if (loose_parse_oid(&ref->oid, &ref_file) < 0) { + if (loose_parse_oid(&ref->oid, name, &ref_file) < 0) { git_buf_free(&ref_file); git__free(ref); return -1; } - ref->flags = GIT_PACKREF_WAS_LOOSE; + ref->flags = PACKREF_WAS_LOOSE; *ref_out = ref; git_buf_free(&ref_file); @@ -430,12 +465,12 @@ static int loose_lookup( goto done; } - *out = git_reference__alloc(backend->refdb, ref_name, NULL, target); + *out = git_reference__alloc_symbolic(ref_name, target); } else { - if ((error = loose_parse_oid(&oid, &ref_file)) < 0) + if ((error = loose_parse_oid(&oid, ref_name, &ref_file)) < 0) goto done; - - *out = git_reference__alloc(backend->refdb, ref_name, &oid, NULL); + + *out = git_reference__alloc(ref_name, &oid, NULL); } if (*out == NULL) @@ -456,19 +491,19 @@ static int packed_map_entry( if (packed_load(backend) < 0) return -1; - + /* Look up on the packfile */ packfile_refs = backend->refcache.packfile; *pos = git_strmap_lookup_index(packfile_refs, ref_name); - + if (!git_strmap_valid_index(packfile_refs, *pos)) { giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref_name); return GIT_ENOTFOUND; } *entry = git_strmap_value_at(packfile_refs, *pos); - + return 0; } @@ -480,13 +515,14 @@ static int packed_lookup( struct packref *entry; khiter_t pos; int error = 0; - + if ((error = packed_map_entry(&entry, &pos, backend, ref_name)) < 0) return error; - if ((*out = git_reference__alloc(backend->refdb, ref_name, &entry->oid, NULL)) == NULL) + if ((*out = git_reference__alloc(ref_name, + &entry->oid, &entry->peel)) == NULL) return -1; - + return 0; } @@ -515,108 +551,239 @@ static int refdb_fs_backend__lookup( return result; } -struct dirent_list_data { - refdb_fs_backend *backend; - size_t repo_path_len; - unsigned int list_type:2; +typedef struct { + git_reference_iterator parent; - git_reference_foreach_cb callback; - void *callback_payload; - int callback_error; -}; + char *glob; + git_vector loose; + unsigned int loose_pos; + khiter_t packed_pos; +} refdb_fs_iter; -static git_ref_t loose_guess_rtype(const git_buf *full_path) +static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) { - git_buf ref_file = GIT_BUF_INIT; - git_ref_t type; + refdb_fs_iter *iter = (refdb_fs_iter *) _iter; + char *loose_path; + size_t i; + + git_vector_foreach(&iter->loose, i, loose_path) { + git__free(loose_path); + } - type = GIT_REF_INVALID; + git_vector_free(&iter->loose); - if (git_futils_readbuffer(&ref_file, full_path->ptr) == 0) { - if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0) - type = GIT_REF_SYMBOLIC; - else - type = GIT_REF_OID; + git__free(iter->glob); + git__free(iter); +} + +static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) +{ + git_strmap *packfile = backend->refcache.packfile; + git_buf path = GIT_BUF_INIT; + git_iterator *fsit; + const git_index_entry *entry = NULL; + + if (!backend->path) /* do nothing if no path for loose refs */ + return 0; + + if (git_buf_printf(&path, "%s/refs", backend->path) < 0) + return -1; + + if (git_iterator_for_filesystem(&fsit, git_buf_cstr(&path), 0, NULL, NULL) < 0) + return -1; + + git_vector_init(&iter->loose, 8, NULL); + git_buf_sets(&path, GIT_REFS_DIR); + + while (!git_iterator_advance(&entry, fsit)) { + const char *ref_name; + khiter_t pos; + + git_buf_truncate(&path, strlen(GIT_REFS_DIR)); + git_buf_puts(&path, entry->path); + ref_name = git_buf_cstr(&path); + + if (git__suffixcmp(ref_name, ".lock") == 0 || + (iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) + continue; + + pos = git_strmap_lookup_index(packfile, ref_name); + if (git_strmap_valid_index(packfile, pos)) { + struct packref *ref = git_strmap_value_at(packfile, pos); + ref->flags |= PACKREF_SHADOWED; + } + + git_vector_insert(&iter->loose, git__strdup(ref_name)); } - git_buf_free(&ref_file); - return type; + git_iterator_free(fsit); + git_buf_free(&path); + + return 0; } -static int _dirent_loose_listall(void *_data, git_buf *full_path) +static int refdb_fs_backend__iterator_next( + git_reference **out, git_reference_iterator *_iter) { - struct dirent_list_data *data = (struct dirent_list_data *)_data; - const char *file_path = full_path->ptr + data->repo_path_len; + refdb_fs_iter *iter = (refdb_fs_iter *)_iter; + refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; + git_strmap *packfile = backend->refcache.packfile; - if (git_path_isdir(full_path->ptr) == true) - return git_path_direach(full_path, _dirent_loose_listall, _data); + while (iter->loose_pos < iter->loose.length) { + const char *path = git_vector_get(&iter->loose, iter->loose_pos++); - /* do not add twice a reference that exists already in the packfile */ - if (git_strmap_exists(data->backend->refcache.packfile, file_path)) - return 0; + if (loose_lookup(out, backend, path) == 0) + return 0; - if (data->list_type != GIT_REF_LISTALL) { - if ((data->list_type & loose_guess_rtype(full_path)) == 0) - return 0; /* we are filtering out this reference */ + giterr_clear(); } - /* Locked references aren't returned */ - if (!git__suffixcmp(file_path, GIT_FILELOCK_EXTENSION)) + while (iter->packed_pos < kh_end(packfile)) { + struct packref *ref = NULL; + + while (!kh_exist(packfile, iter->packed_pos)) { + iter->packed_pos++; + if (iter->packed_pos == kh_end(packfile)) + return GIT_ITEROVER; + } + + ref = kh_val(packfile, iter->packed_pos); + iter->packed_pos++; + + if (ref->flags & PACKREF_SHADOWED) + continue; + + if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0) + continue; + + *out = git_reference__alloc(ref->name, &ref->oid, &ref->peel); + if (*out == NULL) + return -1; + + return 0; + } + + return GIT_ITEROVER; +} + +static int refdb_fs_backend__iterator_next_name( + const char **out, git_reference_iterator *_iter) +{ + refdb_fs_iter *iter = (refdb_fs_iter *)_iter; + refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; + git_strmap *packfile = backend->refcache.packfile; + + while (iter->loose_pos < iter->loose.length) { + const char *path = git_vector_get(&iter->loose, iter->loose_pos++); + + if (git_strmap_exists(packfile, path)) + continue; + + *out = path; return 0; + } + + while (iter->packed_pos < kh_end(packfile)) { + while (!kh_exist(packfile, iter->packed_pos)) { + iter->packed_pos++; + if (iter->packed_pos == kh_end(packfile)) + return GIT_ITEROVER; + } + + *out = kh_key(packfile, iter->packed_pos); + iter->packed_pos++; - if (data->callback(file_path, data->callback_payload)) - data->callback_error = GIT_EUSER; + if (iter->glob && p_fnmatch(iter->glob, *out, 0) != 0) + continue; + + return 0; + } - return data->callback_error; + return GIT_ITEROVER; } -static int refdb_fs_backend__foreach( - git_refdb_backend *_backend, - unsigned int list_type, - git_reference_foreach_cb callback, - void *payload) +static int refdb_fs_backend__iterator( + git_reference_iterator **out, git_refdb_backend *_backend, const char *glob) { + refdb_fs_iter *iter; refdb_fs_backend *backend; - int result; - struct dirent_list_data data; - git_buf refs_path = GIT_BUF_INIT; - const char *ref_name; - void *ref = NULL; - - GIT_UNUSED(ref); assert(_backend); backend = (refdb_fs_backend *)_backend; if (packed_load(backend) < 0) return -1; - - /* list all the packed references first */ - if (list_type & GIT_REF_OID) { - git_strmap_foreach(backend->refcache.packfile, ref_name, ref, { - if (callback(ref_name, payload)) - return GIT_EUSER; - }); + + iter = git__calloc(1, sizeof(refdb_fs_iter)); + GITERR_CHECK_ALLOC(iter); + + if (glob != NULL) + iter->glob = git__strdup(glob); + + iter->parent.next = refdb_fs_backend__iterator_next; + iter->parent.next_name = refdb_fs_backend__iterator_next_name; + iter->parent.free = refdb_fs_backend__iterator_free; + + if (iter_load_loose_paths(backend, iter) < 0) { + refdb_fs_backend__iterator_free((git_reference_iterator *)iter); + return -1; } - /* now list the loose references, trying not to - * duplicate the ref names already in the packed-refs file */ + *out = (git_reference_iterator *)iter; + return 0; +} - data.repo_path_len = strlen(backend->path); - data.list_type = list_type; - data.backend = backend; - data.callback = callback; - data.callback_payload = payload; - data.callback_error = 0; +static bool ref_is_available( + const char *old_ref, const char *new_ref, const char *this_ref) +{ + if (old_ref == NULL || strcmp(old_ref, this_ref)) { + size_t reflen = strlen(this_ref); + size_t newlen = strlen(new_ref); + size_t cmplen = reflen < newlen ? reflen : newlen; + const char *lead = reflen < newlen ? new_ref : this_ref; + + if (!strncmp(new_ref, this_ref, cmplen) && lead[cmplen] == '/') { + return false; + } + } - if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0) + return true; +} + +static int reference_path_available( + refdb_fs_backend *backend, + const char *new_ref, + const char* old_ref, + int force) +{ + struct packref *this_ref; + + if (packed_load(backend) < 0) return -1; - result = git_path_direach(&refs_path, _dirent_loose_listall, &data); + if (!force) { + int exists; - git_buf_free(&refs_path); + if (refdb_fs_backend__exists(&exists, (git_refdb_backend *)backend, new_ref) < 0) + return -1; + + if (exists) { + giterr_set(GITERR_REFERENCE, + "Failed to write reference '%s': a reference with " + " that name already exists.", new_ref); + return GIT_EEXISTS; + } + } - return data.callback_error ? GIT_EUSER : result; + git_strmap_foreach_value(backend->refcache.packfile, this_ref, { + if (!ref_is_available(old_ref, new_ref, this_ref->name)) { + giterr_set(GITERR_REFERENCE, + "The path to reference '%s' collides with an existing one", new_ref); + return -1; + } + }); + + return 0; } static int loose_write(refdb_fs_backend *backend, const git_reference *ref) @@ -627,8 +794,7 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) /* Remove a possibly existing empty directory hierarchy * which name would collide with the reference name */ - if (git_futils_rmdir_r(ref->name, backend->path, - GIT_RMDIR_SKIP_NONEMPTY) < 0) + if (git_futils_rmdir_r(ref->name, backend->path, GIT_RMDIR_SKIP_NONEMPTY) < 0) return -1; if (git_buf_joinpath(&ref_path, backend->path, ref->name) < 0) @@ -678,14 +844,7 @@ static int packed_find_peel(refdb_fs_backend *backend, struct packref *ref) { git_object *object; - if (ref->flags & GIT_PACKREF_HAS_PEEL) - return 0; - - /* - * Only applies to tags, i.e. references - * in the /refs/tags folder - */ - if (git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) != 0) + if (ref->flags & PACKREF_HAS_PEEL || ref->flags & PACKREF_CANNOT_PEEL) return 0; /* @@ -706,7 +865,7 @@ static int packed_find_peel(refdb_fs_backend *backend, struct packref *ref) * Find the object pointed at by this tag */ git_oid_cpy(&ref->peel, git_tag_target_id(tag)); - ref->flags |= GIT_PACKREF_HAS_PEEL; + ref->flags |= PACKREF_HAS_PEEL; /* * The reference has now cached the resolved OID, and is @@ -739,7 +898,7 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file) * This obviously only applies to tags. * The required peels have already been loaded into `ref->peel_target`. */ - if (ref->flags & GIT_PACKREF_HAS_PEEL) { + if (ref->flags & PACKREF_HAS_PEEL) { char peel[GIT_OID_HEXSZ + 1]; git_oid_fmt(peel, &ref->peel); peel[GIT_OID_HEXSZ] = 0; @@ -776,7 +935,7 @@ static int packed_remove_loose( for (i = 0; i < packing_list->length; ++i) { struct packref *ref = git_vector_get(packing_list, i); - if ((ref->flags & GIT_PACKREF_WAS_LOOSE) == 0) + if ((ref->flags & PACKREF_WAS_LOOSE) == 0) continue; if (git_buf_joinpath(&full_path, backend->path, ref->name) < 0) @@ -895,66 +1054,113 @@ cleanup_memory: static int refdb_fs_backend__write( git_refdb_backend *_backend, - const git_reference *ref) + const git_reference *ref, + int force) { refdb_fs_backend *backend; + int error; assert(_backend); backend = (refdb_fs_backend *)_backend; + error = reference_path_available(backend, ref->name, NULL, force); + if (error < 0) + return error; + return loose_write(backend, ref); } static int refdb_fs_backend__delete( git_refdb_backend *_backend, - const git_reference *ref) + const char *ref_name) { refdb_fs_backend *backend; - git_repository *repo; git_buf loose_path = GIT_BUF_INIT; struct packref *pack_ref; khiter_t pack_ref_pos; - int error = 0, pack_error; - bool loose_deleted; + int error = 0; + bool loose_deleted = 0; assert(_backend); - assert(ref); + assert(ref_name); backend = (refdb_fs_backend *)_backend; - repo = backend->repo; /* If a loose reference exists, remove it from the filesystem */ - - if (git_buf_joinpath(&loose_path, repo->path_repository, ref->name) < 0) + if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0) return -1; if (git_path_isfile(loose_path.ptr)) { error = p_unlink(loose_path.ptr); loose_deleted = 1; } - + git_buf_free(&loose_path); if (error != 0) return error; /* If a packed reference exists, remove it from the packfile and repack */ + error = packed_map_entry(&pack_ref, &pack_ref_pos, backend, ref_name); + + if (error == GIT_ENOTFOUND) + return loose_deleted ? 0 : GIT_ENOTFOUND; - if ((pack_error = packed_map_entry(&pack_ref, &pack_ref_pos, backend, ref->name)) == 0) { + if (error == 0) { git_strmap_delete_at(backend->refcache.packfile, pack_ref_pos); git__free(pack_ref); - error = packed_write(backend); } - - if (pack_error == GIT_ENOTFOUND) - error = loose_deleted ? 0 : GIT_ENOTFOUND; - else - error = pack_error; return error; } +static int refdb_fs_backend__rename( + git_reference **out, + git_refdb_backend *_backend, + const char *old_name, + const char *new_name, + int force) +{ + refdb_fs_backend *backend; + git_reference *old, *new; + int error; + + assert(_backend); + backend = (refdb_fs_backend *)_backend; + + error = reference_path_available(backend, new_name, old_name, force); + if (error < 0) + return error; + + error = refdb_fs_backend__lookup(&old, _backend, old_name); + if (error < 0) + return error; + + error = refdb_fs_backend__delete(_backend, old_name); + if (error < 0) { + git_reference_free(old); + return error; + } + + new = realloc(old, sizeof(git_reference) + strlen(new_name) + 1); + memcpy(new->name, new_name, strlen(new_name) + 1); + + error = loose_write(backend, new); + if (error < 0) { + git_reference_free(new); + return error; + } + + if (out) { + *out = new; + } else { + git_reference_free(new); + } + + return 0; +} + static int refdb_fs_backend__compress(git_refdb_backend *_backend) { refdb_fs_backend *backend; @@ -993,28 +1199,76 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) backend = (refdb_fs_backend *)_backend; refcache_free(&backend->refcache); + git__free(backend->path); git__free(backend); } +static int setup_namespace(git_buf *path, git_repository *repo) +{ + char *parts, *start, *end; + + /* Not all repositories have a path */ + if (repo->path_repository == NULL) + return 0; + + /* Load the path to the repo first */ + git_buf_puts(path, repo->path_repository); + + /* if the repo is not namespaced, nothing else to do */ + if (repo->namespace == NULL) + return 0; + + parts = end = git__strdup(repo->namespace); + if (parts == NULL) + return -1; + + /** + * From `man gitnamespaces`: + * namespaces which include a / will expand to a hierarchy + * of namespaces; for example, GIT_NAMESPACE=foo/bar will store + * refs under refs/namespaces/foo/refs/namespaces/bar/ + */ + while ((start = git__strsep(&end, "/")) != NULL) { + git_buf_printf(path, "refs/namespaces/%s/", start); + } + + git_buf_printf(path, "refs/namespaces/%s/refs", end); + git__free(parts); + + /* Make sure that the folder with the namespace exists */ + if (git_futils_mkdir_r(git_buf_cstr(path), repo->path_repository, 0777) < 0) + return -1; + + /* Return the root of the namespaced path, i.e. without the trailing '/refs' */ + git_buf_rtruncate_at_char(path, '/'); + return 0; +} + int git_refdb_backend_fs( git_refdb_backend **backend_out, - git_repository *repository, - git_refdb *refdb) + git_repository *repository) { + git_buf path = GIT_BUF_INIT; refdb_fs_backend *backend; backend = git__calloc(1, sizeof(refdb_fs_backend)); GITERR_CHECK_ALLOC(backend); backend->repo = repository; - backend->path = repository->path_repository; - backend->refdb = refdb; + + if (setup_namespace(&path, repository) < 0) { + git__free(backend); + return -1; + } + + backend->path = git_buf_detach(&path); backend->parent.exists = &refdb_fs_backend__exists; backend->parent.lookup = &refdb_fs_backend__lookup; - backend->parent.foreach = &refdb_fs_backend__foreach; + backend->parent.iterator = &refdb_fs_backend__iterator; backend->parent.write = &refdb_fs_backend__write; backend->parent.delete = &refdb_fs_backend__delete; + backend->parent.rename = &refdb_fs_backend__rename; backend->parent.compress = &refdb_fs_backend__compress; backend->parent.free = &refdb_fs_backend__free; |