From: Tracey Emery Subject: Re: branches in got.conf To: Stefan Sperling Cc: gameoftrees@openbsd.org Date: Fri, 25 Sep 2020 14:54:20 -0600 On Fri, Sep 25, 2020 at 12:35:39AM +0200, Stefan Sperling wrote: > 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? > Now with 100% more comments down there ... > 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); > + } > + tabs > + } > + > 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. */ trailing space also in struct got_remote_repo there is an extra tab, just as a note > 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}, -- Tracey Emery