commit b8adfa5529205d58ab21c9c8fc76b50068ebbaa2 from: Stefan Sperling date: Fri Sep 25 21:35:10 2020 UTC add "branch" keyword to got.conf which specifies a list of branches to fetch ok tracey commit - cad0b9e88686cab44e7532dfaaa0b5cdd47beb10 commit + b8adfa5529205d58ab21c9c8fc76b50068ebbaa2 blob - fd46852d20b5897c487045e6e0c4d99e0bda0508 blob + d21f191972b4fc066ea0888f9cdd02172ef49fde --- got/got.c +++ got/got.c @@ -2094,6 +2094,14 @@ cmd_fetch(int argc, char *argv[]) if (remote == NULL) { error = got_error_path(remote_name, GOT_ERR_NO_REMOTE); goto done; + } + + if (TAILQ_EMPTY(&wanted_branches) && remote->nbranches > 0) { + for (i = 0; i < remote->nbranches; i++) { + got_pathlist_append(&wanted_branches, + remote->branches[i], NULL); + } + } error = got_fetch_parse_uri(&proto, &host, &port, &server_path, blob - f1c3eb07dd31dd3a4620452bfdfab1b4119d3c66 blob + 4995cf2a725ee8bd5c325bcf65e0bafcf67f4f87 --- got/got.conf.5 +++ got/got.conf.5 @@ -105,6 +105,15 @@ for details. If not specified, the default port of the specified .Cm protocol will be used. +.It Ic branch Brq Ar branch ... +Specify one or more branches which +.Cm got fetch +should fetch from the remote repository by default. +The list of branches specified here can be overridden at the +.Cm got fetch +command line with the +.Fl b +option. .It Ic mirror-references Ar yes | no This option controls the behaviour of .Cm got fetch @@ -138,6 +147,7 @@ remote "origin" { server git.gameoftrees.org protocol git repository got + branch { "main" } } .Ed .Pp blob - 2b104798d08e7adbf100ae6c9d7a0877630dacdd blob + 20f873a5d4df17522f28c52407c564cdb5d0e583 --- include/got_repository.h +++ include/got_repository.h @@ -51,15 +51,25 @@ const char *got_repo_get_gitconfig_owner(struct got_re struct got_remote_repo { char *name; char *url; - + /* * If set, references are mirrored 1:1 into the local repository. * If not set, references are mapped into "refs/remotes/$name/". */ int mirror_references; + + /* Branches to fetch by default. */ + int nbranches; + char **branches; }; -/* Obtain the list of remote repositories parsed from gitconfig. */ +/* + * Free data allocated for the specified remote repository. + * Do not free the remote_repo pointer itself. + */ +void got_repo_free_remote_repo_data(struct got_remote_repo *); + +/* Obtain the list of remote repositories parsed from gitconfig. */ void got_repo_get_gitconfig_remotes(int *, const struct got_remote_repo **, struct got_repository *); blob - 51acfb2fde45abd2e9073411ad36ae9a24fed30e blob + 6c638e9d018fe07c5b7e6949507b353ea5495e3e --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -377,8 +377,10 @@ struct got_imsg_remote { size_t name_len; size_t url_len; int mirror_references; + int nbranches; /* Followed by name_len + url_len data bytes. */ + /* Followed by nbranches GOT_IMSG_GITCONFIG_STR_VAL messages. */ } __attribute__((__packed__)); /* blob - d3c83b325581b556b7bca0faa5d7f3fbc611c63b blob + 7133ec58bdbaf535f13ad65c71428d7eb891a975 --- lib/gotconfig.c +++ lib/gotconfig.c @@ -138,10 +138,8 @@ got_gotconfig_free(struct got_gotconfig *conf) free(conf->author); - for (i = 0; i < conf->nremotes; i++) { - free(conf->remotes[i].name); - free(conf->remotes[i].url); - } + for (i = 0; i < conf->nremotes; i++) + got_repo_free_remote_repo_data(&conf->remotes[i]); free(conf->remotes); free(conf); } blob - 77debd84e15bb4334632363ebe637cfbe88f4202 blob + 0cacbdd05b05c1e5021ca3c240f513d4476a0d8d --- lib/privsep.c +++ lib/privsep.c @@ -1783,6 +1783,18 @@ got_privsep_recv_gitconfig_int(int *val, struct imsgbu imsg_free(&imsg); return err; +} + +static void +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); } const struct got_error * @@ -1838,6 +1850,7 @@ got_privsep_recv_gitconfig_remotes(struct got_remote_r switch (imsg.hdr.type) { case GOT_IMSG_GITCONFIG_REMOTE: remote = &(*remotes)[*nremotes]; + memset(remote, 0, sizeof(*remote)); if (datalen < sizeof(iremote)) { err = got_error(GOT_ERR_PRIVSEP_LEN); break; @@ -1859,10 +1872,12 @@ got_privsep_recv_gitconfig_remotes(struct got_remote_r iremote.name_len, iremote.url_len); if (remote->url == NULL) { err = got_error_from_errno("strndup"); - free(remote->name); + free_remote_data(remote); break; } remote->mirror_references = iremote.mirror_references; + remote->nbranches = 0; + remote->branches = NULL; (*nremotes)++; break; default: @@ -1877,10 +1892,8 @@ got_privsep_recv_gitconfig_remotes(struct got_remote_r if (err) { int i; - for (i = 0; i < *nremotes; i++) { - free((*remotes)[i].name); - free((*remotes)[i].url); - } + for (i = 0; i < *nremotes; i++) + free_remote_data(&(*remotes)[i]); free(*remotes); *remotes = NULL; *nremotes = 0; @@ -1970,6 +1983,7 @@ 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) @@ -2025,6 +2039,7 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r struct got_remote_repo *remote; const size_t min_datalen = MIN(sizeof(struct got_imsg_error), sizeof(iremote)); + int i; err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen); if (err) @@ -2041,6 +2056,7 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r break; case GOT_IMSG_GOTCONFIG_REMOTE: remote = &(*remotes)[*nremotes]; + memset(remote, 0, sizeof(*remote)); if (datalen < sizeof(iremote)) { err = got_error(GOT_ERR_PRIVSEP_LEN); break; @@ -2062,10 +2078,31 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r iremote.name_len, iremote.url_len); if (remote->url == NULL) { err = got_error_from_errno("strndup"); - free(remote->name); + free_remote_data(remote); break; } remote->mirror_references = iremote.mirror_references; + if (iremote.nbranches > 0) { + remote->branches = recallocarray(NULL, 0, + iremote.nbranches, sizeof(char *)); + if (remote->branches == NULL) { + err = got_error_from_errno("calloc"); + free_remote_data(remote); + break; + } + } + remote->nbranches = 0; + for (i = 0; i < iremote.nbranches; i++) { + char *branch; + err = got_privsep_recv_gotconfig_str(&branch, + ibuf); + if (err) { + free_remote_data(remote); + goto done; + } + remote->branches[i] = branch; + remote->nbranches++; + } (*nremotes)++; break; default: @@ -2077,13 +2114,11 @@ got_privsep_recv_gotconfig_remotes(struct got_remote_r if (err) break; } - +done: if (err) { int i; - for (i = 0; i < *nremotes; i++) { - free((*remotes)[i].name); - free((*remotes)[i].url); - } + for (i = 0; i < *nremotes; i++) + free_remote_data(&(*remotes)[i]); free(*remotes); *remotes = NULL; *nremotes = 0; blob - 4c90acd881a0f23ba1cb6479838a991e6e8eb61f blob + 5fe931f9c74dc53f1a6814a342b8eefc7d80f439 --- lib/repository.c +++ lib/repository.c @@ -681,14 +681,28 @@ got_repo_close(struct got_repository *repo) got_gotconfig_free(repo->gotconfig); free(repo->gitconfig_author_name); free(repo->gitconfig_author_email); - for (i = 0; i < repo->ngitconfig_remotes; i++) { - free(repo->gitconfig_remotes[i].name); - free(repo->gitconfig_remotes[i].url); - } + for (i = 0; i < repo->ngitconfig_remotes; i++) + got_repo_free_remote_repo_data(&repo->gitconfig_remotes[i]); free(repo->gitconfig_remotes); free(repo); return err; +} + +void +got_repo_free_remote_repo_data(struct got_remote_repo *repo) +{ + int i; + + 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; } const struct got_error * blob - e7234d40124938d4a98b3294599098e47661c6f5 blob + 631e11236b4eb40c77f4df72632afabd30ee931e --- libexec/got-read-gotconfig/got-read-gotconfig.c +++ libexec/got-read-gotconfig/got-read-gotconfig.c @@ -142,7 +142,16 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, struct got_imsg_remote iremote; size_t len = sizeof(iremote); struct ibuf *wbuf; + struct node_branch *branch; + int nbranches = 0; + branch = repo->branch; + while (branch) { + branch = branch->next; + nbranches++; + } + + iremote.nbranches = nbranches; iremote.mirror_references = repo->mirror_references; iremote.name_len = strlen(repo->name); @@ -189,6 +198,14 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, free(url); url = NULL; + + branch = repo->branch; + while (branch) { + err = send_gotconfig_str(ibuf, branch->branch_name); + if (err) + break; + branch = branch->next; + } } free(url); blob - ab55bd31f17ddbcdf0a483b21903f7e00a588c20 blob + a909f144a9ab2a4715e7975ad3fcbd8764181cde --- libexec/got-read-gotconfig/gotconfig.h +++ libexec/got-read-gotconfig/gotconfig.h @@ -15,6 +15,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +struct node_branch { + char *branch_name; + struct node_branch *next; + struct node_branch *tail; +}; + struct gotconfig_remote_repo { TAILQ_ENTRY(gotconfig_remote_repo) entry; char *name; @@ -23,6 +29,7 @@ struct gotconfig_remote_repo { char *protocol; int port; int mirror_references; + struct node_branch *branch; }; TAILQ_HEAD(gotconfig_remote_repo_list, gotconfig_remote_repo); blob - aa7193a5915cdb3f05afe31c665b6ac7fbf31480 blob + 2ae503c4da4198a918f6bbb1bed217eb6bbba8b0 --- libexec/got-read-gotconfig/parse.y +++ libexec/got-read-gotconfig/parse.y @@ -86,6 +86,7 @@ typedef struct { union { int64_t number; char *string; + struct node_branch *branch; } v; int lineno; } YYSTYPE; @@ -93,11 +94,13 @@ typedef struct { %} %token ERROR -%token REMOTE REPOSITORY SERVER PORT PROTOCOL MIRROR_REFERENCES AUTHOR +%token REMOTE REPOSITORY SERVER PORT PROTOCOL MIRROR_REFERENCES BRANCH +%token AUTHOR %token STRING %token NUMBER %type boolean portplain %type numberstring +%type branch xbranch branch_list %% @@ -137,8 +140,30 @@ portplain : numberstring { YYERROR; } free($1); + } + ; +branch : /* empty */ { $$ = NULL; } + | xbranch { $$ = $1; } + | '{' optnl branch_list '}' { $$ = $3; } + ; +xbranch : STRING { + $$ = calloc(1, sizeof(struct node_branch)); + if ($$ == NULL) { + yyerror("calloc"); + YYERROR; + } + $$->branch_name = $1; + $$->tail = $$; + } + ; +branch_list : xbranch optnl { $$ = $1; } + | branch_list comma xbranch optnl { + $1->tail->next = $3; + $1->tail = $3; + $$ = $1; } ; + remoteopts2 : remoteopts2 remoteopts1 nl | remoteopts1 optnl ; @@ -174,6 +199,9 @@ remoteopts1 : REPOSITORY STRING { } | PORT portplain { remote->port = $2; + } + | BRANCH branch { + remote->branch = $2; } ; remote : REMOTE STRING { @@ -211,6 +239,9 @@ optnl : '\n' optnl | /* empty */ ; nl : '\n' optnl + ; +comma : ',' + | /* empty */ ; %% @@ -254,6 +285,7 @@ lookup(char *s) /* This has to be sorted always. */ static const struct keywords keywords[] = { {"author", AUTHOR}, + {"branch", BRANCH}, {"mirror-references", MIRROR_REFERENCES}, {"port", PORT}, {"protocol", PROTOCOL},