summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2013-05-29 22:47:37 +0200
committerVicent Marti <tanoku@gmail.com>2013-05-29 22:47:37 +0200
commitec24e542969f9d49e41e4c2cb3eac2259b1818c2 (patch)
treefd201dedeabda91e8a0e63b27eeb24093a759988 /src
parent56960b8396d3aef0b39f32aa7a9749202f925ada (diff)
downloadlibgit2-ec24e542969f9d49e41e4c2cb3eac2259b1818c2.tar.gz
What are the chances, really
Diffstat (limited to 'src')
-rw-r--r--src/clone.c2
-rw-r--r--src/refdb.c80
-rw-r--r--src/refdb.h7
-rw-r--r--src/refdb_fs.c132
-rw-r--r--src/refs.c125
-rw-r--r--src/repository.c4
-rw-r--r--src/tag.c2
7 files changed, 203 insertions, 149 deletions
diff --git a/src/clone.c b/src/clone.c
index 7ebdb5765..72906c3ce 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -241,7 +241,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
}
/* Not master. Check all the other refs. */
- if (git_reference_foreach(
+ if (git_reference_foreach_name(
repo,
reference_matches_remote_head,
&head_info) < 0)
diff --git a/src/refdb.c b/src/refdb.c
index 6cb879288..e0701d347 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -114,99 +114,65 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
assert(db && db->backend && out && ref_name);
- if (!(error = db->backend->lookup(&ref, db->backend, ref_name))) {
- ref->db = db;
- *out = ref;
- } else {
- *out = NULL;
- }
+ error = db->backend->lookup(&ref, db->backend, ref_name);
+ if (error < 0)
+ return error;
+
+ GIT_REFCOUNT_INC(db);
+ ref->db = db;
- return error;
+ *out = ref;
+ return 0;
}
-int git_refdb_iterator(git_reference_iterator **out, git_refdb *db)
+int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{
if (!db->backend || !db->backend->iterator) {
giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
return -1;
}
- if (db->backend->iterator(out, db->backend) < 0)
+ if (db->backend->iterator(out, db->backend, glob) < 0)
return -1;
+ GIT_REFCOUNT_INC(db);
+ (*out)->db = db;
+
return 0;
}
-int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob)
+int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter)
{
- if (!db->backend) {
- giterr_set(GITERR_REFERENCE, "There are no backends loaded");
- return -1;
- }
-
- if (db->backend->iterator_glob)
- return db->backend->iterator_glob(out, db->backend, glob);
+ int error;
- /* If the backend doesn't support glob-filtering themselves, we have to do it */
- if (db->backend->iterator(out, db->backend) < 0)
- return -1;
+ if ((error = iter->next(out, iter)) < 0)
+ return error;
- (*out)->glob = git__strdup(glob);
- if (!(*out)->glob) {
- db->backend->iterator_free(*out);
- return -1;
- }
+ GIT_REFCOUNT_INC(iter->db);
+ (*out)->db = iter->db;
return 0;
}
-int git_refdb_next(git_reference **out, git_reference_iterator *iter)
+int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter)
{
- int error;
-
- if (!iter->glob) {
- if ((error = iter->backend->next(out, iter)) < 0)
- return error;
-
- (*out)->db = iter->backend;
- return 0;
- }
-
- /* If the iterator has a glob, we need to filter */
- while ((error = iter->backend->next(out, iter)) == 0) {
- if (!p_fnmatch(iter->glob, (*out)->name, 0)) {
- (*out)->db = iter->backend;
- return 0;
- }
-
- git_reference_free(*out);
- }
-
- return error;
+ return iter->next_name(out, iter);
}
void git_refdb_iterator_free(git_reference_iterator *iter)
{
- git__free(iter->glob);
- iter->backend->iterator_free(iter);
+ GIT_REFCOUNT_DEC(iter->db, refdb_free);
+ iter->free(iter);
}
-struct glob_cb_data {
- const char *glob;
- git_reference_foreach_cb callback;
- void *payload;
-};
-
int git_refdb_write(git_refdb *db, const git_reference *ref)
{
assert(db && db->backend);
-
return db->backend->write(db->backend, ref);
}
int git_refdb_delete(struct git_refdb *db, const git_reference *ref)
{
assert(db && db->backend);
-
return db->backend->delete(db->backend, ref);
}
diff --git a/src/refdb.h b/src/refdb.h
index 82522e191..1dcd70da8 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -26,13 +26,12 @@ int git_refdb_lookup(
git_refdb *refdb,
const char *ref_name);
-int git_refdb_iterator(git_reference_iterator **out, git_refdb *db);
-int git_refdb_iterator_glob(git_reference_iterator **out, git_refdb *db, const char *glob);
-int git_refdb_next(git_reference **out, git_reference_iterator *iter);
+int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob);
+int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter);
+int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter);
void git_refdb_iterator_free(git_reference_iterator *iter);
int git_refdb_write(git_refdb *refdb, const git_reference *ref);
-
int git_refdb_delete(git_refdb *refdb, const git_reference *ref);
#endif
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 457964570..ecd033de0 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -556,34 +556,12 @@ static int refdb_fs_backend__lookup(
typedef struct {
git_reference_iterator parent;
+ char *glob;
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;
- refdb_fs_backend *backend;
-
- assert(_backend);
- backend = (refdb_fs_backend *)_backend;
-
- if (packed_load(backend) < 0)
- return -1;
-
- iter = git__calloc(1, sizeof(refdb_fs_iter));
- GITERR_CHECK_ALLOC(iter);
-
- iter->parent.backend = _backend;
- 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;
@@ -595,14 +573,14 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
}
git_vector_free(&iter->loose);
+
+ git__free(iter->glob);
git__free(iter);
}
-static int iter_load_loose_paths(refdb_fs_iter *iter)
+static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
{
- refdb_fs_backend *backend = (refdb_fs_backend *) iter->parent.backend;
git_strmap *packfile = backend->refcache.packfile;
-
git_buf path = GIT_BUF_INIT;
git_iterator *fsit;
const git_index_entry *entry = NULL;
@@ -624,7 +602,8 @@ static int iter_load_loose_paths(refdb_fs_iter *iter)
git_buf_puts(&path, entry->path);
ref_name = git_buf_cstr(&path);
- if (git__suffixcmp(ref_name, ".lock") == 0) {
+ if (git__suffixcmp(ref_name, ".lock") == 0 ||
+ (iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) {
git_iterator_advance(NULL, fsit);
continue;
}
@@ -645,10 +624,11 @@ static int iter_load_loose_paths(refdb_fs_iter *iter)
return 0;
}
-static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_iter)
+static int refdb_fs_backend__iterator_next(
+ git_reference **out, git_reference_iterator *_iter)
{
refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
- refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.backend;
+ refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend;
git_strmap *packfile = backend->refcache.packfile;
while (iter->loose_pos < iter->loose.length) {
@@ -660,19 +640,23 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_
giterr_clear();
}
- if (iter->packed_pos < kh_end(packfile)) {
+ while (iter->packed_pos < kh_end(packfile)) {
struct packref *ref = NULL;
- do {
- 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);
+ while (!kh_exist(packfile, iter->packed_pos)) {
iter->packed_pos++;
- } while (ref->flags & PACKREF_SHADOWED);
+ 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)
@@ -684,6 +668,74 @@ static int refdb_fs_backend__next(git_reference **out, git_reference_iterator *_
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 (iter->glob && p_fnmatch(iter->glob, *out, 0) != 0)
+ continue;
+
+ return 0;
+ }
+
+ return GIT_ITEROVER;
+}
+
+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;
+
+ assert(_backend);
+ backend = (refdb_fs_backend *)_backend;
+
+ if (packed_load(backend) < 0)
+ return -1;
+
+ 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;
+ }
+
+ *out = (git_reference_iterator *)iter;
+ return 0;
+}
+
+
static int loose_write(refdb_fs_backend *backend, const git_reference *ref)
{
git_filebuf file = GIT_FILEBUF_INIT;
@@ -1118,8 +1170,6 @@ int git_refdb_backend_fs(
backend->parent.exists = &refdb_fs_backend__exists;
backend->parent.lookup = &refdb_fs_backend__lookup;
backend->parent.iterator = &refdb_fs_backend__iterator;
- backend->parent.next = &refdb_fs_backend__next;
- backend->parent.iterator_free = &refdb_fs_backend__iterator_free;
backend->parent.write = &refdb_fs_backend__write;
backend->parent.delete = &refdb_fs_backend__delete;
backend->parent.compress = &refdb_fs_backend__compress;
diff --git a/src/refs.c b/src/refs.c
index 43231b0cf..a8583de19 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -104,20 +104,20 @@ struct reference_available_t {
int available;
};
-static int _reference_available_cb(const char *ref, void *data)
+static int _reference_available_cb(const char *refname, void *data)
{
struct reference_available_t *d;
- assert(ref && data);
+ assert(refname && data);
d = (struct reference_available_t *)data;
- if (!d->old_ref || strcmp(d->old_ref, ref)) {
- size_t reflen = strlen(ref);
+ if (!d->old_ref || strcmp(d->old_ref, refname)) {
+ size_t reflen = strlen(refname);
size_t newlen = strlen(d->new_ref);
size_t cmplen = reflen < newlen ? reflen : newlen;
- const char *lead = reflen < newlen ? d->new_ref : ref;
+ const char *lead = reflen < newlen ? d->new_ref : refname;
- if (!strncmp(d->new_ref, ref, cmplen) && lead[cmplen] == '/') {
+ if (!strncmp(d->new_ref, refname, cmplen) && lead[cmplen] == '/') {
d->available = 0;
return -1;
}
@@ -126,6 +126,9 @@ static int _reference_available_cb(const char *ref, void *data)
return 0;
}
+/**
+ * TODO: this should be part of the FS backend
+ */
static int reference_path_available(
git_repository *repo,
const char *ref,
@@ -138,8 +141,7 @@ static int reference_path_available(
data.old_ref = old_ref;
data.available = 1;
- error = git_reference_foreach(
- repo, _reference_available_cb, (void *)&data);
+ error = git_reference_foreach_name(repo, _reference_available_cb, (void *)&data);
if (error < 0)
return error;
@@ -430,6 +432,7 @@ static int reference__create(
ref = git_reference__alloc_symbolic(name, symbolic);
}
+ /* TODO: this needs to be written more explicitly */
GITERR_CHECK_ALLOC(ref);
ref->db = refdb;
@@ -558,6 +561,7 @@ int git_reference_rename(
if (result == NULL)
return -1;
+ /* TODO: this is bad */
result->db = ref->db;
/* Check if we have to update HEAD. */
@@ -623,14 +627,69 @@ int git_reference_foreach(
void *payload)
{
git_reference_iterator *iter;
- const char *name;
+ git_reference *ref;
int error;
if (git_reference_iterator_new(&iter, repo) < 0)
return -1;
- while ((error = git_reference_next(&name, iter)) == 0) {
- if (callback(name, payload)) {
+ while ((error = git_reference_next(&ref, iter)) == 0) {
+ if (callback(ref, payload)) {
+ error = GIT_EUSER;
+ goto out;
+ }
+ }
+
+ if (error == GIT_ITEROVER)
+ error = 0;
+
+out:
+ git_reference_iterator_free(iter);
+ return error;
+}
+
+int git_reference_foreach_name(
+ git_repository *repo,
+ git_reference_foreach_name_cb callback,
+ void *payload)
+{
+ git_reference_iterator *iter;
+ const char *refname;
+ int error;
+
+ if (git_reference_iterator_new(&iter, repo) < 0)
+ return -1;
+
+ while ((error = git_reference_next_name(&refname, iter)) == 0) {
+ if (callback(refname, payload)) {
+ error = GIT_EUSER;
+ goto out;
+ }
+ }
+
+ if (error == GIT_ITEROVER)
+ error = 0;
+
+out:
+ git_reference_iterator_free(iter);
+ return error;
+}
+
+int git_reference_foreach_glob(
+ git_repository *repo,
+ const char *glob,
+ git_reference_foreach_name_cb callback,
+ void *payload)
+{
+ git_reference_iterator *iter;
+ const char *refname;
+ int error;
+
+ if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
+ return -1;
+
+ while ((error = git_reference_next_name(&refname, iter)) == 0) {
+ if (callback(refname, payload)) {
error = GIT_EUSER;
goto out;
}
@@ -651,22 +710,28 @@ int git_reference_iterator_new(git_reference_iterator **out, git_repository *rep
if (git_repository_refdb__weakptr(&refdb, repo) < 0)
return -1;
- return git_refdb_iterator(out, refdb);
+ return git_refdb_iterator(out, refdb, NULL);
}
-int git_reference_iterator_glob_new(git_reference_iterator **out, git_repository *repo, const char *glob)
+int git_reference_iterator_glob_new(
+ git_reference_iterator **out, git_repository *repo, const char *glob)
{
git_refdb *refdb;
if (git_repository_refdb__weakptr(&refdb, repo) < 0)
return -1;
- return git_refdb_iterator_glob(out, refdb, glob);
+ return git_refdb_iterator(out, refdb, glob);
}
int git_reference_next(git_reference **out, git_reference_iterator *iter)
{
- return git_refdb_next(out, iter);
+ return git_refdb_iterator_next(out, iter);
+}
+
+int git_reference_next_name(const char **out, git_reference_iterator *iter)
+{
+ return git_refdb_iterator_next_name(out, iter);
}
void git_reference_iterator_free(git_reference_iterator *iter)
@@ -693,7 +758,7 @@ int git_reference_list(
if (git_vector_init(&ref_list, 8, NULL) < 0)
return -1;
- if (git_reference_foreach(
+ if (git_reference_foreach_name(
repo, &cb__reflist_add, (void *)&ref_list) < 0) {
git_vector_free(&ref_list);
return -1;
@@ -991,34 +1056,6 @@ int git_reference__update_terminal(
return reference__update_terminal(repo, ref_name, oid, 0);
}
-int git_reference_foreach_glob(
- git_repository *repo,
- const char *glob,
- git_reference_foreach_cb callback,
- void *payload)
-{
- git_reference_iterator *iter;
- const char *name;
- int error;
-
- if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
- return -1;
-
- while ((error = git_reference_next(&name, iter)) == 0) {
- if (callback(name, payload)) {
- error = GIT_EUSER;
- goto out;
- }
- }
-
- if (error == GIT_ITEROVER)
- error = 0;
-
-out:
- git_reference_iterator_free(iter);
- return error;
-}
-
int git_reference_has_log(
git_reference *ref)
{
diff --git a/src/repository.c b/src/repository.c
index 28505e822..2e7a334c9 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1473,12 +1473,14 @@ static int at_least_one_cb(const char *refname, void *payload)
static int repo_contains_no_reference(git_repository *repo)
{
- int error = git_reference_foreach(repo, at_least_one_cb, NULL);
+ int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
if (error == GIT_EUSER)
return 0;
+
if (!error)
return 1;
+
return error;
}
diff --git a/src/tag.c b/src/tag.c
index ecf3876cb..71f4c1eb1 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -440,7 +440,7 @@ int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data)
data.cb_data = cb_data;
data.repo = repo;
- return git_reference_foreach(repo, &tags_cb, &data);
+ return git_reference_foreach_name(repo, &tags_cb, &data);
}
typedef struct {