commit - cad0b9e88686cab44e7532dfaaa0b5cdd47beb10
commit + b8adfa5529205d58ab21c9c8fc76b50068ebbaa2
blob - fd46852d20b5897c487045e6e0c4d99e0bda0508
blob + d21f191972b4fc066ea0888f9cdd02172ef49fde
--- got/got.c
+++ got/got.c
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
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
server git.gameoftrees.org
protocol git
repository got
+ branch { "main" }
}
.Ed
.Pp
blob - 2b104798d08e7adbf100ae6c9d7a0877630dacdd
blob + 20f873a5d4df17522f28c52407c564cdb5d0e583
--- include/got_repository.h
+++ include/got_repository.h
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
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
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
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 *
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;
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:
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;
return err;
}
+
const struct got_error *
got_privsep_recv_gotconfig_remotes(struct got_remote_repo **remotes,
int *nremotes, struct imsgbuf *ibuf)
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)
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;
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:
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
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
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);
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
* 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;
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
union {
int64_t number;
char *string;
+ struct node_branch *branch;
} v;
int lineno;
} YYSTYPE;
%}
%token ERROR
-%token REMOTE REPOSITORY SERVER PORT PROTOCOL MIRROR_REFERENCES AUTHOR
+%token REMOTE REPOSITORY SERVER PORT PROTOCOL MIRROR_REFERENCES BRANCH
+%token AUTHOR
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.number> boolean portplain
%type <v.string> numberstring
+%type <v.branch> branch xbranch branch_list
%%
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
;
}
| PORT portplain {
remote->port = $2;
+ }
+ | BRANCH branch {
+ remote->branch = $2;
}
;
remote : REMOTE STRING {
| /* empty */
;
nl : '\n' optnl
+ ;
+comma : ','
+ | /* empty */
;
%%
/* This has to be sorted always. */
static const struct keywords keywords[] = {
{"author", AUTHOR},
+ {"branch", BRANCH},
{"mirror-references", MIRROR_REFERENCES},
{"port", PORT},
{"protocol", PROTOCOL},