Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2013-05-28 19:50:47 +0400
committerVicent Marti <tanoku@gmail.com>2013-05-28 19:50:47 +0400
commit2638a03affdf57c989f573d48afca3b849cb4c1f (patch)
treed54556235e5e031da81f411e42aacfaa13b3a565 /src/refdb_fs.c
parent9007c53faecf51be7f166172682008d16f7d617a (diff)
This refs iterator pleases the gods.
Diffstat (limited to 'src/refdb_fs.c')
-rw-r--r--src/refdb_fs.c147
1 files changed, 69 insertions, 78 deletions
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 7de56a1a0..97f0b07c4 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -29,7 +29,8 @@ GIT__USE_STRMAP;
enum {
PACKREF_HAS_PEEL = 1,
PACKREF_WAS_LOOSE = 2,
- PACKREF_CANNOT_PEEL = 4
+ PACKREF_CANNOT_PEEL = 4,
+ PACKREF_SHADOWED = 8,
};
enum {
@@ -552,27 +553,16 @@ 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;
-
- git_reference_foreach_cb callback;
- void *callback_payload;
- int callback_error;
-};
-
typedef struct {
git_reference_iterator parent;
- unsigned int loose;
- /* packed */
- git_strmap *h;
- khiter_t k;
- /* loose */
- git_iterator *fsiter;
- git_buf buf;
+
+ git_vector loose;
+ unsigned int loose_pos;
+ khiter_t packed_pos;
} refdb_fs_iter;
+static int iter_load_loose_paths(refdb_fs_iter *iter);
+
static int refdb_fs_backend__iterator(git_reference_iterator **out, git_refdb_backend *_backend)
{
refdb_fs_iter *iter;
@@ -588,103 +578,104 @@ static int refdb_fs_backend__iterator(git_reference_iterator **out, git_refdb_ba
GITERR_CHECK_ALLOC(iter);
iter->parent.backend = _backend;
- iter->h = backend->refcache.packfile;
- iter->k = kh_begin(backend->refcache.packfile);
+ iter_load_loose_paths(iter);
*out = (git_reference_iterator *)iter;
-
return 0;
}
static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
{
refdb_fs_iter *iter = (refdb_fs_iter *) _iter;
+ char *loose_path;
+ size_t i;
- git_buf_free(&iter->buf);
- git_iterator_free(iter->fsiter);
+ git_vector_foreach(&iter->loose, i, loose_path) {
+ free(loose_path);
+ }
+
+ git_vector_free(&iter->loose);
git__free(iter);
}
-static int iter_packed(const char **out, refdb_fs_iter *iter)
+static int iter_load_loose_paths(refdb_fs_iter *iter)
{
- /* Move forward to the next entry */
- while (!kh_exist(iter->h, iter->k)) {
- iter->k++;
- if (iter->k == kh_end(iter->h))
- return GIT_ITEROVER;
- }
+ refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
+ git_strmap *packfile = backend->refcache.packfile;
- *out = kh_key(iter->h, iter->k);
- iter->k++;
+ git_buf path = GIT_BUF_INIT;
+ git_iterator *fsit;
+ const git_index_entry *entry = NULL;
- return 0;
-}
+ if (git_buf_printf(&path, "%s/refs", backend->path) < 0)
+ return -1;
-static int iter_loose(const char **out, refdb_fs_iter *iter)
-{
- const git_index_entry *entry;
- int retry;
- git_strmap *packfile_refs;
- refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
+ if (git_iterator_for_filesystem(&fsit, git_buf_cstr(&path), 0, NULL, NULL) < 0)
+ return -1;
- packfile_refs = backend->refcache.packfile;
+ git_vector_init(&iter->loose, 8, NULL);
+ git_buf_sets(&path, GIT_REFS_DIR);
- do {
+ while (!git_iterator_current(&entry, fsit) && entry) {
+ const char *ref_name;
khiter_t pos;
- if (git_iterator_current(&entry, iter->fsiter) < 0)
- return -1;
- git_buf_clear(&iter->buf);
- if (!entry)
- return GIT_ITEROVER;
+ git_buf_truncate(&path, strlen(GIT_REFS_DIR));
+ git_buf_puts(&path, entry->path);
+ ref_name = git_buf_cstr(&path);
- if (git_buf_printf(&iter->buf, "refs/%s", entry->path) < 0)
- return -1;
+ if (git__suffixcmp(ref_name, ".lock") == 0) {
+ git_iterator_advance(NULL, fsit);
+ continue;
+ }
- git_iterator_advance(NULL, iter->fsiter);
+ 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;
+ }
- /* Skip this one if we already listed it in packed */
- pos = git_strmap_lookup_index(packfile_refs, git_buf_cstr(&iter->buf));
- retry = 0;
- if (git_strmap_valid_index(packfile_refs, pos) ||
- !git_reference_is_valid_name(git_buf_cstr(&iter->buf)))
- retry = 1;
+ git_vector_insert(&iter->loose, git__strdup(ref_name));
+ git_iterator_advance(NULL, fsit);
+ }
- *out = git_buf_cstr(&iter->buf);
- } while (retry);
+ git_iterator_free(fsit);
+ git_buf_free(&path);
return 0;
}
-static int iter_loose_setup(refdb_fs_iter *iter)
+static int refdb_fs_backend__next(const char **out, git_reference_iterator *_iter)
{
+ refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
+ git_strmap *packfile = backend->refcache.packfile;
- git_buf_clear(&iter->buf);
- if (git_buf_printf(&iter->buf, "%s/refs", backend->path) < 0)
- return -1;
+ if (iter->loose_pos < iter->loose.length) {
+ const char *path = git_vector_get(&iter->loose, iter->loose_pos++);
+ *out = path;
+ return 0;
+ }
- return git_iterator_for_filesystem(&iter->fsiter, git_buf_cstr(&iter->buf), 0, NULL, NULL);
-}
+ if (iter->packed_pos < kh_end(packfile)) {
+ struct packref *ref = NULL;
-static int refdb_fs_backend__next(const char **out, git_reference_iterator *_iter)
-{
- refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
+ do {
+ while (!kh_exist(packfile, iter->packed_pos)) {
+ iter->packed_pos++;
+ if (iter->packed_pos == kh_end(packfile))
+ return GIT_ITEROVER;
+ }
- if (iter->loose)
- return iter_loose(out, iter);
+ ref = kh_val(packfile, iter->packed_pos);
+ iter->packed_pos++;
+ } while (ref->flags & PACKREF_SHADOWED);
- if (iter->k != kh_end(iter->h)) {
- int error = iter_packed(out, iter);
- if (error != GIT_ITEROVER)
- return error;
+ *out = ref->name;
+ return 0;
}
- if (iter_loose_setup(iter) < 0)
- return -1;
- iter->loose = 1;
-
- return iter_loose(out, iter);
+ return GIT_ITEROVER;
}
static int loose_write(refdb_fs_backend *backend, const git_reference *ref)