diff options
| -rw-r--r-- | examples/log.c | 6 | ||||
| -rw-r--r-- | include/git2/config.h | 11 | ||||
| -rw-r--r-- | include/git2/remote.h | 15 | ||||
| -rw-r--r-- | include/git2/sys/config.h | 1 | ||||
| -rw-r--r-- | src/config.c | 13 | ||||
| -rw-r--r-- | src/config_file.c | 89 | ||||
| -rw-r--r-- | src/merge.c | 2 | ||||
| -rw-r--r-- | src/netops.c | 7 | ||||
| -rw-r--r-- | src/pack-objects.c | 7 | ||||
| -rw-r--r-- | src/remote.c | 9 | ||||
| -rw-r--r-- | src/transports/git.c | 4 | ||||
| -rw-r--r-- | src/transports/smart.h | 4 | ||||
| -rw-r--r-- | src/transports/smart_pkt.c | 30 | ||||
| -rw-r--r-- | src/transports/smart_protocol.c | 53 | ||||
| -rw-r--r-- | src/transports/ssh.c | 11 | ||||
| -rw-r--r-- | tests-clar/clone/nonetwork.c | 9 | ||||
| -rw-r--r-- | tests-clar/config/multivar.c | 65 | ||||
| -rw-r--r-- | tests-clar/network/remote/remotes.c | 25 | ||||
| -rw-r--r-- | tests-clar/network/urlparse.c | 7 |
19 files changed, 293 insertions, 75 deletions
diff --git a/examples/log.c b/examples/log.c index 4c2df07c9..81b056cc5 100644 --- a/examples/log.c +++ b/examples/log.c @@ -125,7 +125,7 @@ static int add_revision(struct log_state *s, const char *revstr) static void print_time(const git_time *intime, const char *prefix) { char sign, out[32]; - struct tm intm; + struct tm *intm; int offset, hours, minutes; time_t t; @@ -142,8 +142,8 @@ static void print_time(const git_time *intime, const char *prefix) t = (time_t)intime->time + (intime->offset * 60); - gmtime_r(&t, &intm); - strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); + intm = gmtime(&t); + strftime(out, sizeof(out), "%a %b %e %T %Y", intm); printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } diff --git a/include/git2/config.h b/include/git2/config.h index f14415148..95da4bc03 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -435,6 +435,17 @@ GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const GIT_EXTERN(int) git_config_delete_entry(git_config *cfg, const char *name); /** + * Deletes one or several entries from a multivar in the local config file. + * + * @param cfg where to look for the variables + * @param name the variable's name + * @param regexp a regular expression to indicate which values to delete + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp); + +/** * Perform an operation on each config variable. * * The callback receives the normalized name and value of each variable diff --git a/include/git2/remote.h b/include/git2/remote.h index f4cd1cbfa..b9cf86ef1 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -357,21 +357,6 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo); GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check); /** - * Set a credentials acquisition callback for this remote. If the remote is - * not available for anonymous access, then you must set this callback in order - * to provide credentials to the transport at the time of authentication - * failure so that retry can be performed. - * - * @param remote the remote to configure - * @param cred_acquire_cb The credentials acquisition callback to use (defaults - * to NULL) - */ -GIT_EXTERN(void) git_remote_set_cred_acquire_cb( - git_remote *remote, - git_cred_acquire_cb cred_acquire_cb, - void *payload); - -/** * Sets a custom transport for the remote. The caller can use this function * to bypass the automatic discovery of a transport by URL scheme (i.e. * http://, https://, git://) and supply their own transport to be used diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 7572ace51..419ad7ea7 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -61,6 +61,7 @@ struct git_config_backend { int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); + int (*del_multivar)(struct git_config_backend *, const char *key, const char *regexp); int (*iterator)(git_config_iterator **, struct git_config_backend *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); diff --git a/src/config.c b/src/config.c index c98d6a52d..0d9471383 100644 --- a/src/config.c +++ b/src/config.c @@ -862,6 +862,19 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex return file->set_multivar(file, name, regexp, value); } +int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp) +{ + git_config_backend *file; + file_internal *internal; + + internal = git_vector_get(&cfg->files, 0); + if (!internal || !internal->file) + return config_error_nofiles(name); + file = internal->file; + + return file->del_multivar(file, name, regexp); +} + int git_config_next(git_config_entry **entry, git_config_iterator *iter) { return iter->next(entry, iter); diff --git a/src/config_file.c b/src/config_file.c index 8fb43b990..6abf60621 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -120,6 +120,18 @@ static void cvar_free(cvar_t *var) git__free(var); } +static int cvar_length(cvar_t *var) +{ + int length = 0; + + while (var) { + length++; + var = var->next; + } + + return length; +} + int git_config_file_normalize_section(char *start, char *end) { char *scan; @@ -531,6 +543,80 @@ static int config_delete(git_config_backend *cfg, const char *name) return result; } +static int config_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp) +{ + cvar_t *var, *prev = NULL, *new_head = NULL; + cvar_t **to_delete; + int to_delete_idx; + diskfile_backend *b = (diskfile_backend *)cfg; + char *key; + regex_t preg; + int result; + khiter_t pos; + + if ((result = git_config__normalize_name(name, &key)) < 0) + return result; + + pos = git_strmap_lookup_index(b->values, key); + + if (!git_strmap_valid_index(b->values, pos)) { + giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name); + git__free(key); + return GIT_ENOTFOUND; + } + + var = git_strmap_value_at(b->values, pos); + + result = regcomp(&preg, regexp, REG_EXTENDED); + if (result < 0) { + git__free(key); + giterr_set_regex(&preg, result); + regfree(&preg); + return -1; + } + + to_delete = git__calloc(cvar_length(var), sizeof(cvar_t *)); + GITERR_CHECK_ALLOC(to_delete); + to_delete_idx = 0; + + while (var != NULL) { + cvar_t *next = var->next; + + if (regexec(&preg, var->entry->value, 0, NULL, 0) == 0) { + // If we are past the head, reattach previous node to next one, + // otherwise set the new head for the strmap. + if (prev != NULL) { + prev->next = next; + } else { + new_head = next; + } + + to_delete[to_delete_idx++] = var; + } else { + prev = var; + } + + var = next; + } + + if (new_head != NULL) { + git_strmap_set_value_at(b->values, pos, new_head); + } else { + git_strmap_delete_at(b->values, pos); + } + + if (to_delete_idx > 0) + result = config_write(b, key, &preg, NULL); + + while (to_delete_idx-- > 0) + cvar_free(to_delete[to_delete_idx]); + + git__free(key); + git__free(to_delete); + regfree(&preg); + return result; +} + int git_config_file__ondisk(git_config_backend **out, const char *path) { diskfile_backend *backend; @@ -548,6 +634,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; + backend->parent.del_multivar = config_delete_multivar; backend->parent.iterator = config_iterator_new; backend->parent.refresh = config_refresh; backend->parent.free = backend_free; @@ -1214,7 +1301,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p } /* multiline variable? we need to keep reading lines to match */ - if (preg != NULL) { + if (preg != NULL && section_matches) { data_start = post_start; continue; } diff --git a/src/merge.c b/src/merge.c index b07e8c52f..a22801e48 100644 --- a/src/merge.c +++ b/src/merge.c @@ -285,7 +285,7 @@ int git_repository_mergehead_foreach(git_repository *repo, if ((error = git_oid_fromstr(&oid, line)) < 0) goto cleanup; - if (cb(&oid, payload) < 0) { + if (cb(&oid, payload) != 0) { error = GIT_EUSER; goto cleanup; } diff --git a/src/netops.c b/src/netops.c index 7a61ef820..7e13f12e7 100644 --- a/src/netops.c +++ b/src/netops.c @@ -679,9 +679,10 @@ int gitno_extract_url_parts( slash = strchr(url, '/'); at = strchr(url, '@'); - if (slash == NULL) { - giterr_set(GITERR_NET, "Malformed URL: missing /"); - return -1; + if (!slash || + (colon && (slash < colon))) { + giterr_set(GITERR_NET, "Malformed URL"); + return GIT_EINVALIDSPEC; } start = url; diff --git a/src/pack-objects.c b/src/pack-objects.c index 938b28fde..2d0f564d1 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -824,7 +824,7 @@ static unsigned long free_unpacked(struct unpacked *n) static int find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int *list_size, unsigned int window, - unsigned int depth) + int depth) { git_pobject *po; git_buf zbuf = GIT_BUF_INIT; @@ -839,8 +839,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, for (;;) { struct unpacked *n = array + idx; - unsigned int max_depth; - int j, best_base = -1; + int max_depth, j, best_base = -1; git_packbuilder__progress_lock(pb); if (!*list_size) { @@ -1033,7 +1032,7 @@ static void *threaded_find_deltas(void *arg) static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int list_size, unsigned int window, - unsigned int depth) + int depth) { struct thread_params *p; int i, ret, active_threads = 0; diff --git a/src/remote.c b/src/remote.c index bdfa08642..3528b1c46 100644 --- a/src/remote.c +++ b/src/remote.c @@ -365,16 +365,18 @@ static int update_config_refspec(const git_remote *remote, git_config *config, i const char *dir; size_t i; int error = 0; + const char *cname; push = direction == GIT_DIRECTION_PUSH; dir = push ? "push" : "fetch"; if (git_buf_printf(&name, "remote.%s.%s", remote->name, dir) < 0) return -1; + cname = git_buf_cstr(&name); /* Clear out the existing config */ while (!error) - error = git_config_delete_entry(config, git_buf_cstr(&name)); + error = git_config_delete_multivar(config, cname, ".*"); if (error != GIT_ENOTFOUND) return error; @@ -385,8 +387,11 @@ static int update_config_refspec(const git_remote *remote, git_config *config, i if (spec->push != push) continue; + // "$^" is a unmatcheable regexp: it will not match anything at all, so + // all values will be considered new and we will not replace any + // present value. if ((error = git_config_set_multivar( - config, git_buf_cstr(&name), "", spec->string)) < 0) { + config, cname, "$^", spec->string)) < 0) { goto cleanup; } } diff --git a/src/transports/git.c b/src/transports/git.c index 3a0b86345..79a9e7dd4 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -179,7 +179,7 @@ static int _git_uploadpack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host, *port, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; git_stream *s; *stream = NULL; @@ -235,7 +235,7 @@ static int _git_receivepack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host, *port, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; git_stream *s; *stream = NULL; diff --git a/src/transports/smart.h b/src/transports/smart.h index 7fda27d4e..5232e54de 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -16,6 +16,7 @@ #define GIT_CAP_OFS_DELTA "ofs-delta" #define GIT_CAP_MULTI_ACK "multi_ack" +#define GIT_CAP_MULTI_ACK_DETAILED "multi_ack_detailed" #define GIT_CAP_SIDE_BAND "side-band" #define GIT_CAP_SIDE_BAND_64K "side-band-64k" #define GIT_CAP_INCLUDE_TAG "include-tag" @@ -40,7 +41,7 @@ enum git_pkt_type { GIT_PKT_UNPACK, }; -/* Used for multi-ack */ +/* Used for multi_ack and mutli_ack_detailed */ enum git_ack_status { GIT_ACK_NONE, GIT_ACK_CONTINUE, @@ -113,6 +114,7 @@ typedef struct transport_smart_caps { int common:1, ofs_delta:1, multi_ack: 1, + multi_ack_detailed: 1, side_band:1, side_band_64k:1, include_tag:1, diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index a1f623c78..2bb09c750 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -39,7 +39,7 @@ static int flush_pkt(git_pkt **out) return 0; } -/* the rest of the line will be useful for multi_ack */ +/* the rest of the line will be useful for multi_ack and multi_ack_detailed */ static int ack_pkt(git_pkt **out, const char *line, size_t len) { git_pkt_ack *pkt; @@ -62,6 +62,10 @@ static int ack_pkt(git_pkt **out, const char *line, size_t len) if (len >= 7) { if (!git__prefixcmp(line + 1, "continue")) pkt->status = GIT_ACK_CONTINUE; + if (!git__prefixcmp(line + 1, "common")) + pkt->status = GIT_ACK_COMMON; + if (!git__prefixcmp(line + 1, "ready")) + pkt->status = GIT_ACK_READY; } *out = (git_pkt *) pkt; @@ -456,25 +460,27 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca char oid[GIT_OID_HEXSZ +1] = {0}; unsigned int len; - /* Prefer side-band-64k if the server supports both */ - if (caps->side_band) { - if (caps->side_band_64k) - git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); - else - git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); - } - if (caps->ofs_delta) - git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); - - if (caps->multi_ack) + /* Prefer multi_ack_detailed */ + if (caps->multi_ack_detailed) + git_buf_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " "); + else if (caps->multi_ack) git_buf_puts(&str, GIT_CAP_MULTI_ACK " "); + /* Prefer side-band-64k if the server supports both */ + if (caps->side_band_64k) + git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); + else if (caps->side_band) + git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); + if (caps->include_tag) git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " "); if (caps->thin_pack) git_buf_puts(&str, GIT_CAP_THIN_PACK " "); + if (caps->ofs_delta) + git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); + if (git_buf_oom(&str)) return -1; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 8833b2816..651901b1b 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -97,6 +97,13 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps) continue; } + /* Keep multi_ack_detailed before multi_ack */ + if (!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK_DETAILED)) { + caps->common = caps->multi_ack_detailed = 1; + ptr += strlen(GIT_CAP_MULTI_ACK_DETAILED); + continue; + } + if (!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK)) { caps->common = caps->multi_ack = 1; ptr += strlen(GIT_CAP_MULTI_ACK); @@ -236,6 +243,32 @@ on_error: return -1; } +static int wait_while_ack(gitno_buffer *buf) +{ + int error; + git_pkt_ack *pkt = NULL; + + while (1) { + git__free(pkt); + + if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0) + return error; + + if (pkt->type == GIT_PKT_NAK) + break; + + if (pkt->type == GIT_PKT_ACK && + (pkt->status != GIT_ACK_CONTINUE || + pkt->status != GIT_ACK_COMMON)) { + git__free(pkt); + break; + } + } + + git__free(pkt); + return 0; +} + int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *refs, size_t count) { transport_smart *t = (transport_smart *)transport; @@ -287,7 +320,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c goto on_error; git_buf_clear(&data); - if (t->caps.multi_ack) { + if (t->caps.multi_ack || t->caps.multi_ack_detailed) { if ((error = store_common(t)) < 0) goto on_error; } else { @@ -365,7 +398,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_revwalk_free(walk); /* Now let's eat up whatever the server gives us */ - if (!t->caps.multi_ack) { + if (!t->caps.multi_ack && !t->caps.multi_ack_detailed) { pkt_type = recv_pkt(NULL, buf); if (pkt_type < 0) { @@ -375,22 +408,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c return -1; } } else { - git_pkt_ack *pkt; - do { - if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0) - return error; - - if (pkt->type == GIT_PKT_NAK || - (pkt->type == GIT_PKT_ACK && pkt->status != GIT_ACK_CONTINUE)) { - git__free(pkt); - break; - } - - git__free(pkt); - } while (1); + error = wait_while_ack(buf); } - return 0; + return error; on_error: git_revwalk_free(walk); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 6ce673d5e..4e2834b49 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -213,10 +213,6 @@ static int git_ssh_extract_url_parts( colon = strchr(url, ':'); - if (colon == NULL) { - giterr_set(GITERR_NET, "Malformed URL: missing :"); - return -1; - } at = strchr(url, '@'); if (at) { @@ -228,6 +224,11 @@ static int git_ssh_extract_url_parts( *username = NULL; } + if (colon == NULL || (colon < start)) { + giterr_set(GITERR_NET, "Malformed URL"); + return -1; + } + *host = git__substrdup(start, colon - start); GITERR_CHECK_ALLOC(*host); @@ -316,7 +317,7 @@ static int _git_ssh_setup_conn( const char *cmd, git_smart_subtransport_stream **stream) { - char *host, *port=NULL, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 071e3d09f..a286e2a8f 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -46,7 +46,7 @@ void test_clone_nonetwork__cleanup(void) cl_fixture_cleanup("./foo"); } -void test_clone_nonetwork__bad_url(void) +void test_clone_nonetwork__bad_urls(void) { /* Clone should clean up the mess if the URL isn't a git repository */ cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); @@ -54,6 +54,13 @@ void test_clone_nonetwork__bad_url(void) g_options.bare = true; cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); cl_assert(!git_path_exists("./foo")); + + cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", + "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "arrbee:my/bad:password@github.com:1111/strange:words.git", + "./foo", &g_options)); } void test_clone_nonetwork__do_not_clean_existing_directory(void) diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index 0d552d65e..afdb1e5f4 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -221,3 +221,68 @@ void test_config_multivar__replace_multiple(void) git_config_free(cfg); } + +void test_config_multivar__delete(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "github")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); +} + +void test_config_multivar__delete_multiple(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "git")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); +} + +void test_config_multivar__delete_notfound(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + cl_git_fail_with(git_config_delete_multivar(cfg, "remote.ab.noturl", "git"), GIT_ENOTFOUND); + + git_config_free(cfg); +} diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 6e0eeeb05..7c79b8318 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -150,8 +150,10 @@ void test_network_remote_remotes__add_pushspec(void) void test_network_remote_remotes__save(void) { git_strarray array; - const char *fetch_refspec = "refs/heads/*:refs/remotes/upstream/*"; - const char *push_refspec = "refs/heads/*:refs/heads/*"; + const char *fetch_refspec1 = "refs/heads/ns1/*:refs/remotes/upstream/ns1/*"; + const char *fetch_refspec2 = "refs/heads/ns2/*:refs/remotes/upstream/ns2/*"; + const char *push_refspec1 = "refs/heads/ns1/*:refs/heads/ns1/*"; + const char *push_refspec2 = "refs/heads/ns2/*:refs/heads/ns2/*"; git_remote_free(_remote); _remote = NULL; @@ -160,8 +162,10 @@ void test_network_remote_remotes__save(void) cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); git_remote_clear_refspecs(_remote); - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec)); - cl_git_pass(git_remote_add_push(_remote, push_refspec)); + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); + cl_git_pass(git_remote_add_push(_remote, push_refspec1)); + cl_git_pass(git_remote_add_push(_remote, push_refspec2)); cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); cl_git_pass(git_remote_save(_remote)); git_remote_free(_remote); @@ -171,16 +175,19 @@ void test_network_remote_remotes__save(void) cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); - cl_assert_equal_i(1, (int)array.count); - cl_assert_equal_s(fetch_refspec, array.strings[0]); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(fetch_refspec1, array.strings[0]); + cl_assert_equal_s(fetch_refspec2, array.strings[1]); git_strarray_free(&array); cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); - cl_assert_equal_i(1, (int)array.count); - cl_assert_equal_s(push_refspec, array.strings[0]); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(push_refspec1, array.strings[0]); + cl_assert_equal_s(push_refspec2, array.strings[1]); + git_strarray_free(&array); + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); - git_strarray_free(&array); /* remove the pushurl again and see if we can save that too */ cl_git_pass(git_remote_set_pushurl(_remote, NULL)); diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 274d7e900..15e841b35 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -31,6 +31,13 @@ void test_network_urlparse__trivial(void) cl_assert_equal_p(pass, NULL); } +void test_network_urlparse__bad_url(void) +{ + cl_git_fail_with(gitno_extract_url_parts(&host, &port, &user, &pass, + "github.com/git://github.com/foo/bar.git.git", "443"), + GIT_EINVALIDSPEC); +} + void test_network_urlparse__user(void) { cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, |
