From: Stefan Sperling Subject: branches in got.conf To: gameoftrees@openbsd.org Date: Fri, 25 Sep 2020 00:35:39 +0200 This allows branches in got.conf, as an equivalent to the -b option of got fetch. Branches specified in the configuration file are overridden by any -b options given to got fetch on the command line. I am pondering whether an equivalent to got fetch -R (arbitary references) should be added to got.conf as well. Does anyone have a use case for that? diff e03cc83491255ff69034ff6c824f9ba6062fcddd /home/stsp/src/got blob - fd46852d20b5897c487045e6e0c4d99e0bda0508 file + got/got.c --- got/got.c +++ got/got.c @@ -2096,6 +2096,14 @@ cmd_fetch(int argc, char *argv[]) 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, &repo_name, remote->url); if (error) blob - f1c3eb07dd31dd3a4620452bfdfab1b4119d3c66 file + got/got.conf.5 --- 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 file + include/got_repository.h --- include/got_repository.h +++ include/got_repository.h @@ -57,7 +57,17 @@ struct got_remote_repo { * If not set, references are mapped into "refs/remotes/$name/". */ int mirror_references; + + /* Branches to fetch by default. */ + int nbranches; + char **branches; }; + +/* + * 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 **, blob - 51acfb2fde45abd2e9073411ad36ae9a24fed30e file + lib/got_lib_privsep.h --- 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 file + lib/gotconfig.c --- 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 file + lib/privsep.c --- lib/privsep.c +++ lib/privsep.c @@ -1785,6 +1785,18 @@ got_privsep_recv_gitconfig_int(int *val, struct imsgbu 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 * got_privsep_recv_gitconfig_remotes(struct got_remote_repo **remotes, int *nremotes, struct imsgbuf *ibuf) @@ -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 file + lib/repository.c --- 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 file + libexec/got-read-gotconfig/got-read-gotconfig.c --- 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,12 @@ send_gotconfig_remotes(struct imsgbuf *ibuf, free(url); url = NULL; + + branch = repo->branch; + while (branch) { + err = send_gotconfig_str(ibuf, branch->branch_name); + branch = branch->next; + } } free(url); blob - ab55bd31f17ddbcdf0a483b21903f7e00a588c20 file + libexec/got-read-gotconfig/gotconfig.h --- 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 file + libexec/got-read-gotconfig/parse.y --- 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 %% @@ -139,6 +142,28 @@ portplain : numberstring { 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 ; @@ -175,6 +200,9 @@ remoteopts1 : REPOSITORY STRING { | PORT portplain { remote->port = $2; } + | BRANCH branch { + remote->branch = $2; + } ; remote : REMOTE STRING { static const struct got_error* error; @@ -212,6 +240,9 @@ optnl : '\n' optnl ; nl : '\n' optnl ; +comma : ',' + | /* empty */ + ; %% struct keywords { @@ -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},