From: Stefan Sperling Subject: separate send and fetch config blocks To: gameoftrees@openbsd.org Date: Mon, 30 Aug 2021 13:33:51 +0200 This allows for setting fetch-specific and send-specific options in got.conf. I have added a minimal test which verifies that different repositories can be fetched from and sent to. I have not yet updated got.conf documentation. There is a related problem in parse.y on the main branch: got-read-gotconfig/parse.y: yacc finds 16 shift/reduce conflicts I don't know what impact this has on the behaviour of the patch below, if any. I will look into this next. diff 7eda82c676f6639f83139454d1ab1d487a387741 76884c3fd24036424499f2614fd0f707bba6f8b2 blob - f48598b57aa7474d4174c928c96d948834824f21 blob + 7341a1e00a6e590674fc8184217fe51ee5893014 --- got/got.c +++ got/got.c @@ -2370,20 +2370,20 @@ cmd_fetch(int argc, char *argv[]) if (TAILQ_EMPTY(&wanted_branches)) { if (!fetch_all_branches) fetch_all_branches = remote->fetch_all_branches; - for (i = 0; i < remote->nbranches; i++) { + for (i = 0; i < remote->nfetch_branches; i++) { got_pathlist_append(&wanted_branches, - remote->branches[i], NULL); + remote->fetch_branches[i], NULL); } } if (TAILQ_EMPTY(&wanted_refs)) { - for (i = 0; i < remote->nrefs; i++) { + for (i = 0; i < remote->nfetch_refs; i++) { got_pathlist_append(&wanted_refs, - remote->refs[i], NULL); + remote->fetch_refs[i], NULL); } } error = got_fetch_parse_uri(&proto, &host, &port, &server_path, - &repo_name, remote->url); + &repo_name, remote->fetch_url); if (error) goto done; @@ -7701,7 +7701,7 @@ cmd_send(int argc, char *argv[]) } error = got_fetch_parse_uri(&proto, &host, &port, &server_path, - &repo_name, remote->url); + &repo_name, remote->send_url); if (error) goto done; blob - 9c2f8389ca9fc09f3499080dd949d464f4e85c67 blob + cad8fd52bf0d74bccf0f30ddd4d2173398530bcc --- gotadmin/gotadmin.c +++ gotadmin/gotadmin.c @@ -292,7 +292,7 @@ cmd_info(int argc, char *argv[]) got_gotconfig_get_remotes(&nremotes, &remotes, gotconfig); for (i = 0; i < nremotes; i++) { printf("remote \"%s\": %s\n", remotes[i].name, - remotes[i].url); + remotes[i].fetch_url); } } blob - daa3c3755d6b05b2eb1cfa3014d128ff50539685 blob + 16dcde35f5cc7689f88ae7e3486c4f1fe72aa8f2 --- include/got_repository.h +++ include/got_repository.h @@ -57,10 +57,11 @@ void got_repo_get_gitconfig_extensions(char ***, int * /* Information about one remote repository. */ struct got_remote_repo { char *name; - char *url; + char *fetch_url; + char *send_url; /* - * If set, references are mirrored 1:1 into the local repository. + * If set, fetched references are mirrored 1:1 into our repository. * If not set, references are mapped into "refs/remotes/$name/". */ int mirror_references; @@ -72,12 +73,16 @@ struct got_remote_repo { int fetch_all_branches; /* Branches to fetch by default. */ - int nbranches; - char **branches; + int nfetch_branches; + char **fetch_branches; + /* Branches to send by default. */ + int nsend_branches; + char **send_branches; + /* Other arbitrary references to fetch by default. */ - int nrefs; - char **refs; + int nfetch_refs; + char **fetch_refs; }; /* blob - daaf7f3639f1a1257da430a23bbc5529db74d685 blob + e60e8eb1808bf28909abf7034ebbce19c0dc5100 --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -443,19 +443,24 @@ struct got_imsg_traversed_commits { } __attribute__((__packed__)); /* - * Structure for GOT_IMSG_GITCONFIG_REMOTE data. + * Structure for GOT_IMSG_GOTCONFIG_REMOTE and + * GOT_IMSG_GOTCONFIG_REMOTE data. */ struct got_imsg_remote { size_t name_len; - size_t url_len; + size_t fetch_url_len; + size_t send_url_len; int mirror_references; int fetch_all_branches; - int nbranches; - int nrefs; + int nfetch_branches; + int nsend_branches; + int nfetch_refs; - /* Followed by name_len + url_len data bytes. */ - /* Followed by nbranches GOT_IMSG_GITCONFIG_STR_VAL messages. */ - /* Followed by nrefs GOT_IMSG_GITCONFIG_STR_VAL messages. */ + /* Followed by name_len data bytes. */ + /* Followed by fetch_url_len + send_url_len data bytes. */ + /* Followed by nfetch_branches GOT_IMSG_GITCONFIG_STR_VAL messages. */ + /* Followed by nsend_branches GOT_IMSG_GITCONFIG_STR_VAL messages. */ + /* Followed by nfetch_refs GOT_IMSG_GITCONFIG_STR_VAL messages. */ } __attribute__((__packed__)); /* blob - ecad96e05628c923f414e7613a59a1e54b82bba0 blob + 4846f5880ced5034d986881b1a612ba1062686af --- lib/privsep.c +++ lib/privsep.c @@ -2206,13 +2206,17 @@ free_remote_data(struct got_remote_repo *remote) int i; free(remote->name); - free(remote->url); - for (i = 0; i < remote->nbranches; i++) - free(remote->branches[i]); - free(remote->branches); - for (i = 0; i < remote->nrefs; i++) - free(remote->refs[i]); - free(remote->refs); + free(remote->fetch_url); + free(remote->send_url); + for (i = 0; i < remote->nfetch_branches; i++) + free(remote->fetch_branches[i]); + free(remote->fetch_branches); + for (i = 0; i < remote->nsend_branches; i++) + free(remote->send_branches[i]); + free(remote->send_branches); + for (i = 0; i < remote->nfetch_refs; i++) + free(remote->fetch_refs[i]); + free(remote->fetch_refs); } const struct got_error * @@ -2274,9 +2278,11 @@ got_privsep_recv_gitconfig_remotes(struct got_remote_r break; } memcpy(&iremote, imsg.data, sizeof(iremote)); - if (iremote.name_len == 0 || iremote.url_len == 0 || + if (iremote.name_len == 0 || + iremote.fetch_url_len == 0 || + iremote.send_url_len == 0 || (sizeof(iremote) + iremote.name_len + - iremote.url_len) > datalen) { + iremote.fetch_url_len + iremote.send_url_len) > datalen) { err = got_error(GOT_ERR_PRIVSEP_LEN); break; } @@ -2286,19 +2292,29 @@ got_privsep_recv_gitconfig_remotes(struct got_remote_r err = got_error_from_errno("strndup"); break; } - remote->url = strndup(imsg.data + sizeof(iremote) + - iremote.name_len, iremote.url_len); - if (remote->url == NULL) { + remote->fetch_url = strndup(imsg.data + sizeof(iremote) + + iremote.name_len, iremote.fetch_url_len); + if (remote->fetch_url == NULL) { err = got_error_from_errno("strndup"); free_remote_data(remote); break; } + remote->send_url = strndup(imsg.data + sizeof(iremote) + + iremote.name_len + iremote.fetch_url_len, + iremote.send_url_len); + if (remote->send_url == NULL) { + err = got_error_from_errno("strndup"); + free_remote_data(remote); + break; + } remote->mirror_references = iremote.mirror_references; remote->fetch_all_branches = iremote.fetch_all_branches; - remote->nbranches = 0; - remote->branches = NULL; - remote->nrefs = 0; - remote->refs = NULL; + remote->nfetch_branches = 0; + remote->fetch_branches = NULL; + remote->nsend_branches = 0; + remote->send_branches = NULL; + remote->nfetch_refs = 0; + remote->fetch_refs = NULL; (*nremotes)++; break; default: @@ -2404,7 +2420,6 @@ got_privsep_recv_gotconfig_str(char **str, struct imsg return err; } - const struct got_error * got_privsep_recv_gotconfig_remotes(struct got_remote_repo **remotes, int *nremotes, struct imsgbuf *ibuf) @@ -2483,9 +2498,12 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r break; } memcpy(&iremote, imsg.data, sizeof(iremote)); - if (iremote.name_len == 0 || iremote.url_len == 0 || + if (iremote.name_len == 0 || + (iremote.fetch_url_len == 0 && + iremote.send_url_len == 0) || (sizeof(iremote) + iremote.name_len + - iremote.url_len) > datalen) { + iremote.fetch_url_len + iremote.send_url_len) > + datalen) { err = got_error(GOT_ERR_PRIVSEP_LEN); break; } @@ -2495,26 +2513,35 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r err = got_error_from_errno("strndup"); break; } - remote->url = strndup(imsg.data + sizeof(iremote) + - iremote.name_len, iremote.url_len); - if (remote->url == NULL) { + remote->fetch_url = strndup(imsg.data + + sizeof(iremote) + iremote.name_len, + iremote.fetch_url_len); + if (remote->fetch_url == NULL) { err = got_error_from_errno("strndup"); free_remote_data(remote); break; } + remote->send_url = strndup(imsg.data + + sizeof(iremote) + iremote.name_len + + iremote.fetch_url_len, iremote.send_url_len); + if (remote->send_url == NULL) { + err = got_error_from_errno("strndup"); + free_remote_data(remote); + break; + } remote->mirror_references = iremote.mirror_references; remote->fetch_all_branches = iremote.fetch_all_branches; - if (iremote.nbranches > 0) { - remote->branches = recallocarray(NULL, 0, - iremote.nbranches, sizeof(char *)); - if (remote->branches == NULL) { + if (iremote.nfetch_branches > 0) { + remote->fetch_branches = recallocarray(NULL, 0, + iremote.nfetch_branches, sizeof(char *)); + if (remote->fetch_branches == NULL) { err = got_error_from_errno("calloc"); free_remote_data(remote); break; } } - remote->nbranches = 0; - for (i = 0; i < iremote.nbranches; i++) { + remote->nfetch_branches = 0; + for (i = 0; i < iremote.nfetch_branches; i++) { char *branch; err = got_privsep_recv_gotconfig_str(&branch, ibuf); @@ -2522,20 +2549,41 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r free_remote_data(remote); goto done; } - remote->branches[i] = branch; - remote->nbranches++; + remote->fetch_branches[i] = branch; + remote->nfetch_branches++; } - if (iremote.nrefs > 0) { - remote->refs = recallocarray(NULL, 0, - iremote.nrefs, sizeof(char *)); - if (remote->refs == NULL) { + if (iremote.nsend_branches > 0) { + remote->send_branches = recallocarray(NULL, 0, + iremote.nsend_branches, sizeof(char *)); + if (remote->send_branches == NULL) { err = got_error_from_errno("calloc"); free_remote_data(remote); break; } } - remote->nrefs = 0; - for (i = 0; i < iremote.nrefs; i++) { + remote->nsend_branches = 0; + for (i = 0; i < iremote.nsend_branches; i++) { + char *branch; + err = got_privsep_recv_gotconfig_str(&branch, + ibuf); + if (err) { + free_remote_data(remote); + goto done; + } + remote->send_branches[i] = branch; + remote->nsend_branches++; + } + if (iremote.nfetch_refs > 0) { + remote->fetch_refs = recallocarray(NULL, 0, + iremote.nfetch_refs, sizeof(char *)); + if (remote->fetch_refs == NULL) { + err = got_error_from_errno("calloc"); + free_remote_data(remote); + break; + } + } + remote->nfetch_refs = 0; + for (i = 0; i < iremote.nfetch_refs; i++) { char *ref; err = got_privsep_recv_gotconfig_str(&ref, ibuf); @@ -2543,8 +2591,8 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r free_remote_data(remote); goto done; } - remote->refs[i] = ref; - remote->nrefs++; + remote->fetch_refs[i] = ref; + remote->nfetch_refs++; } (*nremotes)++; break; blob - 3d857e3a7784f358729bd0b93b349fa77eaa1c10 blob + deb44a1116a2fcd589ff0e0db2fcc4a1c0e2c63d --- lib/repository.c +++ lib/repository.c @@ -786,13 +786,20 @@ got_repo_free_remote_repo_data(struct got_remote_repo free(repo->name); repo->name = NULL; - free(repo->url); - repo->url = NULL; - for (i = 0; i < repo->nbranches; i++) - free(repo->branches[i]); - free(repo->branches); - repo->branches = NULL; - repo->nbranches = 0; + free(repo->fetch_url); + repo->fetch_url = NULL; + free(repo->send_url); + repo->send_url = NULL; + for (i = 0; i < repo->nfetch_branches; i++) + free(repo->fetch_branches[i]); + free(repo->fetch_branches); + repo->fetch_branches = NULL; + repo->nfetch_branches = 0; + for (i = 0; i < repo->nsend_branches; i++) + free(repo->send_branches[i]); + free(repo->send_branches); + repo->send_branches = NULL; + repo->nsend_branches = 0; } const struct got_error * blob - eadef712009b2da9a414361c8395ccbd43f2b1aa blob + 3ce93f09be615d41528eb6af7e5f5a1bd77ce92f --- libexec/got-read-gitconfig/got-read-gitconfig.c +++ libexec/got-read-gitconfig/got-read-gitconfig.c @@ -121,8 +121,10 @@ send_gitconfig_remotes(struct imsgbuf *ibuf, struct go iremote.mirror_references = remotes[i].mirror_references; iremote.name_len = strlen(remotes[i].name); len += iremote.name_len; - iremote.url_len = strlen(remotes[i].url); - len += iremote.url_len; + iremote.fetch_url_len = strlen(remotes[i].fetch_url); + len += iremote.fetch_url_len; + iremote.send_url_len = strlen(remotes[i].send_url); + len += iremote.send_url_len; wbuf = imsg_create(ibuf, GOT_IMSG_GITCONFIG_REMOTE, 0, 0, len); if (wbuf == NULL) @@ -142,12 +144,18 @@ send_gitconfig_remotes(struct imsgbuf *ibuf, struct go ibuf_free(wbuf); return err; } - if (imsg_add(wbuf, remotes[i].url, iremote.url_len) == -1) { + if (imsg_add(wbuf, remotes[i].fetch_url, iremote.fetch_url_len) == -1) { err = got_error_from_errno( "imsg_add GITCONFIG_REMOTE"); ibuf_free(wbuf); return err; } + if (imsg_add(wbuf, remotes[i].send_url, iremote.send_url_len) == -1) { + err = got_error_from_errno( + "imsg_add GITCONFIG_REMOTE"); + ibuf_free(wbuf); + return err; + } wbuf->fd = -1; imsg_close(ibuf, wbuf); @@ -218,13 +226,23 @@ gitconfig_remotes_request(struct imsgbuf *ibuf, struct *end = '\0'; remotes[i].name = name; - remotes[i].url = got_gitconfig_get_str(gitconfig, + remotes[i].fetch_url = got_gitconfig_get_str(gitconfig, node->field, "url"); - if (remotes[i].url == NULL) { + if (remotes[i].fetch_url == NULL) { err = got_error(GOT_ERR_GITCONFIG_SYNTAX); goto done; } + remotes[i].send_url = got_gitconfig_get_str(gitconfig, + node->field, "pushurl"); + if (remotes[i].send_url == NULL) + remotes[i].send_url = got_gitconfig_get_str(gitconfig, + node->field, "url"); + if (remotes[i].send_url == NULL) { + err = got_error(GOT_ERR_GITCONFIG_SYNTAX); + goto done; + } + remotes[i].mirror_references = 0; mirror = got_gitconfig_get_str(gitconfig, node->field, "mirror"); blob - d2b3b15299aad1d02917abf96a7496072e5c4af3 blob + 87b6e325e90f1a5df5293fea97f21d0e0ec8ecdd --- libexec/got-read-gotconfig/got-read-gotconfig.c +++ libexec/got-read-gotconfig/got-read-gotconfig.c @@ -51,28 +51,48 @@ catch_sigint(int signo) } static const struct got_error * -make_repo_url(char **url, struct gotconfig_remote_repo *repo) +make_fetch_url(char **url, struct gotconfig_remote_repo *repo) { const struct got_error *err = NULL; char *s = NULL, *p = NULL; + const char *protocol, *server, *repo_path; + int port; *url = NULL; - if (asprintf(&s, "%s://", repo->protocol) == -1) + if (repo->fetch_config && repo->fetch_config->protocol) + protocol = repo->fetch_config->protocol; + else + protocol = repo->protocol; + if (protocol == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "fetch protocol required for remote repository \"%s\"", + repo->name); + if (asprintf(&s, "%s://", protocol) == -1) return got_error_from_errno("asprintf"); - if (repo->server) { - p = s; - s = NULL; - if (asprintf(&s, "%s%s", p, repo->server) == -1) { - err = got_error_from_errno("asprintf"); - goto done; - } - free(p); - p = NULL; + if (repo->fetch_config && repo->fetch_config->server) + server = repo->fetch_config->server; + else + server = repo->server; + if (server == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "fetch server required for remote repository \"%s\"", + repo->name); + p = s; + s = NULL; + if (asprintf(&s, "%s%s", p, server) == -1) { + err = got_error_from_errno("asprintf"); + goto done; } + free(p); + p = NULL; - if (repo->port) { + if (repo->fetch_config && repo->fetch_config->server) + port = repo->fetch_config->port; + else + port = repo->port; + if (port) { p = s; s = NULL; if (asprintf(&s, "%s:%d", p, repo->port) == -1) { @@ -83,13 +103,82 @@ make_repo_url(char **url, struct gotconfig_remote_repo p = NULL; } - if (repo->repository) { - char *repo_path = repo->repository; - while (repo_path[0] == '/') - repo_path++; + if (repo->fetch_config && repo->fetch_config->repository) + repo_path = repo->fetch_config->repository; + else + repo_path = repo->repository; + if (repo_path == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "fetch repository path required for remote " + "repository \"%s\"", repo->name); + + while (repo_path[0] == '/') + repo_path++; + p = s; + s = NULL; + if (asprintf(&s, "%s/%s", p, repo_path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + free(p); + p = NULL; + + got_path_strip_trailing_slashes(s); +done: + if (err) { + free(s); + free(p); + } else + *url = s; + return err; +} + +static const struct got_error * +make_send_url(char **url, struct gotconfig_remote_repo *repo) +{ + const struct got_error *err = NULL; + char *s = NULL, *p = NULL; + const char *protocol, *server, *repo_path; + int port; + + *url = NULL; + + if (repo->send_config && repo->send_config->protocol) + protocol = repo->send_config->protocol; + else + protocol = repo->protocol; + if (protocol == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "send protocol required for remote repository \"%s\"", + repo->name); + if (asprintf(&s, "%s://", protocol) == -1) + return got_error_from_errno("asprintf"); + + if (repo->send_config && repo->send_config->server) + server = repo->send_config->server; + else + server = repo->server; + if (server == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "send server required for remote repository \"%s\"", + repo->name); + p = s; + s = NULL; + if (asprintf(&s, "%s%s", p, server) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + free(p); + p = NULL; + + if (repo->send_config && repo->send_config->server) + port = repo->send_config->port; + else + port = repo->port; + if (port) { p = s; s = NULL; - if (asprintf(&s, "%s/%s", p, repo_path) == -1) { + if (asprintf(&s, "%s:%d", p, repo->port) == -1) { err = got_error_from_errno("asprintf"); goto done; } @@ -97,6 +186,26 @@ make_repo_url(char **url, struct gotconfig_remote_repo p = NULL; } + if (repo->send_config && repo->send_config->repository) + repo_path = repo->send_config->repository; + else + repo_path = repo->repository; + if (repo_path == NULL) + return got_error_fmt(GOT_ERR_PARSE_CONFIG, + "send repository path required for remote " + "repository \"%s\"", repo->name); + + while (repo_path[0] == '/') + repo_path++; + p = s; + s = NULL; + if (asprintf(&s, "%s/%s", p, repo_path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + free(p); + p = NULL; + got_path_strip_trailing_slashes(s); done: if (err) { @@ -126,7 +235,7 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, const struct got_error *err = NULL; struct got_imsg_remotes iremotes; struct gotconfig_remote_repo *repo; - char *url = NULL; + char *fetch_url = NULL, *send_url = NULL; iremotes.nremotes = nremotes; if (imsg_compose(ibuf, GOT_IMSG_GOTCONFIG_REMOTES, 0, 0, -1, @@ -144,34 +253,63 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, struct ibuf *wbuf; struct node_branch *branch; struct node_ref *ref; - int nbranches = 0, nrefs = 0; + int nfetch_branches = 0, nsend_branches = 0, nfetch_refs = 0; - branch = repo->branch; - while (branch) { - branch = branch->next; - nbranches++; + if (repo->fetch_config && repo->fetch_config->branch) { + branch = repo->fetch_config->branch; + while (branch) { + branch = branch->next; + nfetch_branches++; + } + } else { + branch = repo->branch; + while (branch) { + branch = branch->next; + nfetch_branches++; + } } - ref = repo->ref; + if (repo->send_config && repo->send_config->branch) { + branch = repo->send_config->branch; + while (branch) { + branch = branch->next; + nsend_branches++; + } + } else { + branch = repo->branch; + while (branch) { + branch = branch->next; + nsend_branches++; + } + } + + ref = repo->fetch_ref; while (ref) { ref = ref->next; - nrefs++; + nfetch_refs++; } - iremote.nbranches = nbranches; - iremote.nrefs = nrefs; + iremote.nfetch_branches = nfetch_branches; + iremote.nsend_branches = nsend_branches; + iremote.nfetch_refs = nfetch_refs; iremote.mirror_references = repo->mirror_references; iremote.fetch_all_branches = repo->fetch_all_branches; iremote.name_len = strlen(repo->name); len += iremote.name_len; - err = make_repo_url(&url, repo); + err = make_fetch_url(&fetch_url, repo); if (err) break; - iremote.url_len = strlen(url); - len += iremote.url_len; + iremote.fetch_url_len = strlen(fetch_url); + len += iremote.fetch_url_len; + err = make_send_url(&send_url, repo); + if (err) + break; + iremote.send_url_len = strlen(send_url); + len += iremote.send_url_len; + wbuf = imsg_create(ibuf, GOT_IMSG_GOTCONFIG_REMOTE, 0, 0, len); if (wbuf == NULL) { err = got_error_from_errno( @@ -192,12 +330,18 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, ibuf_free(wbuf); break; } - if (imsg_add(wbuf, url, iremote.url_len) == -1) { + if (imsg_add(wbuf, fetch_url, iremote.fetch_url_len) == -1) { err = got_error_from_errno( "imsg_add GOTCONFIG_REMOTE"); ibuf_free(wbuf); break; } + if (imsg_add(wbuf, send_url, iremote.send_url_len) == -1) { + err = got_error_from_errno( + "imsg_add GOTCONFIG_REMOTE"); + ibuf_free(wbuf); + break; + } wbuf->fd = -1; imsg_close(ibuf, wbuf); @@ -205,18 +349,52 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, if (err) break; - free(url); - url = NULL; + free(fetch_url); + fetch_url = NULL; + free(send_url); + send_url = NULL; - branch = repo->branch; - while (branch) { - err = send_gotconfig_str(ibuf, branch->branch_name); - if (err) - break; - branch = branch->next; + if (repo->fetch_config && repo->fetch_config->branch) { + branch = repo->fetch_config->branch; + while (branch) { + err = send_gotconfig_str(ibuf, + branch->branch_name); + if (err) + break; + branch = branch->next; + } + } else { + branch = repo->branch; + while (branch) { + err = send_gotconfig_str(ibuf, + branch->branch_name); + if (err) + break; + branch = branch->next; + } } - ref = repo->ref; + if (repo->send_config && repo->send_config->branch) { + branch = repo->send_config->branch; + while (branch) { + err = send_gotconfig_str(ibuf, + branch->branch_name); + if (err) + break; + branch = branch->next; + } + } else { + branch = repo->branch; + while (branch) { + err = send_gotconfig_str(ibuf, + branch->branch_name); + if (err) + break; + branch = branch->next; + } + } + + ref = repo->fetch_ref; while (ref) { err = send_gotconfig_str(ibuf, ref->ref_name); if (err) @@ -225,7 +403,8 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, } } - free(url); + free(fetch_url); + free(send_url); return err; } blob - 1ce83bbcfa6c33daba6da2f078860f3a41659d38 blob + 1ce499222101a45de399bd433825c767df869d91 --- libexec/got-read-gotconfig/gotconfig.h +++ libexec/got-read-gotconfig/gotconfig.h @@ -56,7 +56,7 @@ struct gotconfig_remote_repo { int mirror_references; int fetch_all_branches; struct node_branch *branch; - struct node_ref *ref; + struct node_ref *fetch_ref; struct fetch_config *fetch_config; struct send_config *send_config; }; blob - dba94813bce80f3ec22679fe997ba51bbdfc8c58 blob + 4ade508cd285b640d7fa3aaf8064bacfe1641a0c --- libexec/got-read-gotconfig/parse.y +++ libexec/got-read-gotconfig/parse.y @@ -231,7 +231,7 @@ remoteopts1 : REPOSITORY STRING { remote->branch = $2; } | REFERENCE ref { - remote->ref = $2; + remote->fetch_ref = $2; } | FETCH { static const struct got_error* error; blob - b7603c982431e0c17ae7aeb27a58df3481304608 blob + 2c2112b0a45b7a3317cd276452aa270633f87995 --- regress/cmdline/send.sh +++ regress/cmdline/send.sh @@ -1041,7 +1041,123 @@ EOF test_done "$testroot" "$ret" } +test_send_and_fetch_config() { + local testroot=`test_init send_fetch_conf` + local testurl=ssh://127.0.0.1/$testroot + local commit_id=`git_show_head $testroot/repo` + got clone -q $testurl/repo $testroot/repo-clone + ret="$?" + if [ "$ret" != "0" ]; then + echo "got clone command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + got tag -r $testroot/repo -m '1.0' 1.0 >/dev/null + tag_id=`got ref -r $testroot/repo -l | grep "^refs/tags/1.0" \ + | tr -d ' ' | cut -d: -f2` + + cp -R $testroot/repo-clone $testroot/repo-clone2 + got tag -r $testroot/repo-clone2 -m '2.0' 2.0 >/dev/null + tag_id2=`got ref -r $testroot/repo-clone2 -l | grep "^refs/tags/2.0" \ + | tr -d ' ' | cut -d: -f2` + + cat > $testroot/repo/.git/got.conf < $testroot/stdout + if [ "$ret" != "0" ]; then + echo "got ref command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + echo "refs/tags/1.0: $tag_id" >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # fetch tag 2.0 from repo-clone2 + got fetch -q -r $testroot/repo > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + echo "got fetch command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + got ref -l -r $testroot/repo > $testroot/stdout + if [ "$ret" != "0" ]; then + echo "got ref command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + echo "refs/remotes/origin/HEAD: refs/remotes/origin/master" \ + >> $testroot/stdout.expected + echo "refs/remotes/origin/master: $commit_id" \ + >> $testroot/stdout.expected + echo "refs/tags/1.0: $tag_id" >> $testroot/stdout.expected + echo "refs/tags/2.0: $tag_id2" >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # send tag 1.0 to repo-clone + got send -q -r $testroot/repo -t 1.0 > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + echo "got send command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + got ref -l -r $testroot/repo-clone > $testroot/stdout + if [ "$ret" != "0" ]; then + echo "got ref command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + echo "refs/remotes/origin/HEAD: refs/remotes/origin/master" \ + >> $testroot/stdout.expected + echo "refs/remotes/origin/master: $commit_id" \ + >> $testroot/stdout.expected + echo "refs/tags/1.0: $tag_id" >> $testroot/stdout.expected + + cmp -s $testroot/stdout $testroot/stdout.expected + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_send_basic run_test test_send_rebase_required @@ -1052,3 +1168,4 @@ run_test test_send_tags run_test test_send_new_branch run_test test_send_all_branches run_test test_send_to_empty_repo +run_test test_send_and_fetch_config