diff options
author | Vicent Marti <tanoku@gmail.com> | 2013-05-29 22:47:37 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2013-05-29 22:47:37 +0200 |
commit | ec24e542969f9d49e41e4c2cb3eac2259b1818c2 (patch) | |
tree | fd201dedeabda91e8a0e63b27eeb24093a759988 /src | |
parent | 56960b8396d3aef0b39f32aa7a9749202f925ada (diff) | |
download | libgit2-ec24e542969f9d49e41e4c2cb3eac2259b1818c2.tar.gz |
What are the chances, really
Diffstat (limited to 'src')
-rw-r--r-- | src/clone.c | 2 | ||||
-rw-r--r-- | src/refdb.c | 80 | ||||
-rw-r--r-- | src/refdb.h | 7 | ||||
-rw-r--r-- | src/refdb_fs.c | 132 | ||||
-rw-r--r-- | src/refs.c | 125 | ||||
-rw-r--r-- | src/repository.c | 4 | ||||
-rw-r--r-- | src/tag.c | 2 |
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; } @@ -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 { |