commit - bd5895f3726fd0edc272b4c44727f60b5a5132c9
commit + cd95becd3d0ee4fb578daf570177c3550cb19e08
blob - e2e96e4065e6d735452b5a23c4eb1ad179abfa67
blob + d0df1255deadae95cebcf18a88340a0d87666d46
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_REBASE_REQUIRED 111
#define GOT_ERR_REGEX 112
#define GOT_ERR_REF_NAME_MINUS 113
+#define GOT_ERR_GITCONFIG_SYNTAX 114
static const struct got_error {
int code;
{ GOT_ERR_REBASE_REQUIRED,"specified branch must be rebased first" },
{ GOT_ERR_REGEX, "regular expression error" },
{ GOT_ERR_REF_NAME_MINUS, "reference name may not start with '-'" },
+ { GOT_ERR_GITCONFIG_SYNTAX, "gitconfig syntax error" },
};
/*
blob - 7ed477b1d49d732af4362f4100cb33659065f814
blob + 6ef2a57e12d131c901a5bce6196837a91a3618ba
--- include/got_repository.h
+++ include/got_repository.h
/* Obtain global commit author email parsed ~/.gitconfig, else NULL. */
const char *got_repo_get_global_gitconfig_author_email(struct got_repository *);
+/* Information about one remote repository. */
+struct got_remote_repo {
+ char *name;
+ char *url;
+};
+
+/* Obtain the list of remote repositories parsed from gitconfig. */
+void got_repo_get_gitconfig_remotes(int *, struct got_remote_repo **,
+ struct got_repository *);
+
/*
* Obtain paths to various directories within a repository.
* The caller must dispose of a path with free(3).
blob - 1ddfb97d543989190d1cf894c45ed4ed1424f1aa
blob + 5188ecbf5c2419c20c0064c42212be9f91f390f0
--- lib/gitconfig.c
+++ lib/gitconfig.c
tag));
return 0;
}
+
+const struct got_error *
+got_gitconfig_get_section_list(struct got_gitconfig_list **sections,
+ struct got_gitconfig *conf)
+{
+ const struct got_error *err = NULL;
+ struct got_gitconfig_list *list = NULL;
+ struct got_gitconfig_list_node *node = 0;
+ struct got_gitconfig_binding *cb;
+ int i;
+
+ *sections = NULL;
+ list = malloc(sizeof *list);
+ if (!list)
+ return got_error_from_errno("malloc");
+ TAILQ_INIT(&list->fields);
+ list->cnt = 0;
+ for (i = 0; i < nitems(conf->bindings); i++) {
+ for (cb = LIST_FIRST(&conf->bindings[i]); cb;
+ cb = LIST_NEXT(cb, link)) {
+ list->cnt++;
+ node = calloc(1, sizeof *node);
+ if (!node) {
+ err = got_error_from_errno("calloc");
+ goto cleanup;
+ }
+ node->field = strdup(cb->section);
+ if (!node->field) {
+ err = got_error_from_errno("strdup");
+ goto cleanup;
+ }
+ TAILQ_INSERT_TAIL(&list->fields, node, link);
+ }
+ }
+
+ *sections = list;
+ return NULL;
+
+cleanup:
+ free(node);
+ if (list)
+ got_gitconfig_free_list(list);
+ return err;
+}
+
/*
* Build a list of string values out of the comma separated value denoted by
* TAG in SECTION.
blob - 4d61ab3964722d849b94e3048f1cb6a15d2edc3f
blob + 615d2690ac39f3fceb3704b2624a85e8de2ba65c
--- lib/got_lib_gitconfig.h
+++ lib/got_lib_gitconfig.h
struct got_gitconfig;
void got_gitconfig_free_list(struct got_gitconfig_list *);
+const struct got_error *got_gitconfig_get_section_list(
+ struct got_gitconfig_list **, struct got_gitconfig *);
struct got_gitconfig_list *got_gitconfig_get_list(struct got_gitconfig *,
char *, char *);
struct got_gitconfig_list *got_gitconfig_get_tag_list(struct got_gitconfig *, char *);
blob - a37a450e6e18733afec74aa1dc9cb427c9d27acb
blob + b27325da498aa72413f8377303ba76d4012c7813
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST,
GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST,
GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST,
+ GOT_IMSG_GITCONFIG_REMOTES_REQUEST,
GOT_IMSG_GITCONFIG_INT_VAL,
GOT_IMSG_GITCONFIG_STR_VAL,
+ GOT_IMSG_GITCONFIG_REMOTES,
+ GOT_IMSG_GITCONFIG_REMOTE,
};
/* Structure for GOT_IMSG_ERROR. */
int idx;
} __attribute__((__packed__));
+/*
+ * Structure for GOT_IMSG_GITCONFIG_REMOTE data.
+ */
+struct got_imsg_remote {
+ size_t name_len;
+ size_t url_len;
+
+ /* Followed by name_len + url_len data bytes. */
+};
+
+/*
+ * Structure for GOT_IMSG_GITCONFIG_REMOTES data.
+ */
+struct got_imsg_remotes {
+ int nremotes; /* This many GOT_IMSG_GITCONFIG_REMOTE messages follow. */
+};
+
+struct got_remote_repo;
struct got_pack;
struct got_packidx;
struct got_pathlist_head;
struct imsgbuf *);
const struct got_error *got_privsep_send_gitconfig_author_email_req(
struct imsgbuf *);
+const struct got_error *got_privsep_send_gitconfig_remotes_req(
+ struct imsgbuf *);
const struct got_error *got_privsep_send_gitconfig_str(struct imsgbuf *,
const char *);
const struct got_error *got_privsep_recv_gitconfig_str(char **,
struct imsgbuf *);
const struct got_error *got_privsep_send_gitconfig_int(struct imsgbuf *, int);
const struct got_error *got_privsep_recv_gitconfig_int(int *, struct imsgbuf *);
+const struct got_error *got_privsep_send_gitconfig_remotes(struct imsgbuf *,
+ struct got_remote_repo *, int);
+const struct got_error *got_privsep_recv_gitconfig_remotes(
+ struct got_remote_repo **, int *, struct imsgbuf *);
void got_privsep_exec_child(int[2], const char *, const char *);
blob - c304faf993ada599d3d88ab1f3172d00c4ba1225
blob + 93f1734b814bde4b84f85106f95c3646947c45d8
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
char *gitconfig_author_email;
char *global_gitconfig_author_name;
char *global_gitconfig_author_email;
+ int ngitconfig_remotes;
+ struct got_remote_repo *gitconfig_remotes;
};
const struct got_error*got_repo_cache_object(struct got_repository *,
blob - 58bdc0196125fd795f5e78ba1b0c888f248e9fa2
blob + f31cafb2ee6c5d18919265def86f6ddd6193c86d
--- lib/privsep.c
+++ lib/privsep.c
#include "got_object.h"
#include "got_error.h"
#include "got_path.h"
+#include "got_repository.h"
#include "got_lib_sha1.h"
#include "got_lib_delta.h"
GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST, 0, 0, -1, NULL, 0) == -1)
return got_error_from_errno("imsg_compose "
"GITCONFIG_AUTHOR_EMAIL_REQUEST");
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_remotes_req(struct imsgbuf *ibuf)
+{
+ if (imsg_compose(ibuf,
+ GOT_IMSG_GITCONFIG_REMOTES_REQUEST, 0, 0, -1, NULL, 0) == -1)
+ return got_error_from_errno("imsg_compose "
+ "GITCONFIG_REMOTE_REQUEST");
return flush_imsg(ibuf);
}
break;
}
memcpy(val, imsg.data, sizeof(*val));
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ imsg_free(&imsg);
+ return err;
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_remotes(struct imsgbuf *ibuf,
+ struct got_remote_repo *remotes, int nremotes)
+{
+ const struct got_error *err = NULL;
+ struct got_imsg_remotes iremotes;
+ int i;
+
+ iremotes.nremotes = nremotes;
+ if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_REMOTES, 0, 0, -1,
+ &iremotes, sizeof(iremotes)) == -1)
+ return got_error_from_errno("imsg_compose GITCONFIG_REMOTES");
+
+ err = flush_imsg(ibuf);
+ imsg_clear(ibuf);
+ if (err)
+ return err;
+
+ for (i = 0; i < nremotes; i++) {
+ struct got_imsg_remote iremote;
+ size_t len = sizeof(iremote);
+ struct ibuf *wbuf;
+
+ iremote.name_len = strlen(remotes[i].name);
+ len += iremote.name_len;
+ iremote.url_len = strlen(remotes[i].url);
+ len += iremote.url_len;
+
+ wbuf = imsg_create(ibuf, GOT_IMSG_GITCONFIG_REMOTE, 0, 0, len);
+ if (wbuf == NULL)
+ return got_error_from_errno(
+ "imsg_create GITCONFIG_REMOTE");
+
+ if (imsg_add(wbuf, &iremote, sizeof(iremote)) == -1) {
+ err = got_error_from_errno(
+ "imsg_add GIITCONFIG_REMOTE");
+ ibuf_free(wbuf);
+ return err;
+ }
+
+ if (imsg_add(wbuf, remotes[i].name, iremote.name_len) == -1) {
+ err = got_error_from_errno(
+ "imsg_add GIITCONFIG_REMOTE");
+ ibuf_free(wbuf);
+ return err;
+ }
+ if (imsg_add(wbuf, remotes[i].url, iremote.url_len) == -1) {
+ err = got_error_from_errno(
+ "imsg_add GIITCONFIG_REMOTE");
+ ibuf_free(wbuf);
+ return err;
+ }
+
+ wbuf->fd = -1;
+ imsg_close(ibuf, wbuf);
+ err = flush_imsg(ibuf);
+ if (err)
+ return err;
+ }
+
+ return NULL;
+}
+
+const struct got_error *
+got_privsep_recv_gitconfig_remotes(struct got_remote_repo **remotes,
+ int *nremotes, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ size_t datalen;
+ struct got_imsg_remotes iremotes;
+ struct got_imsg_remote iremote;
+
+ *remotes = NULL;
+ *nremotes = 0;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremotes));
+ if (err)
+ return err;
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_GITCONFIG_REMOTES:
+ if (datalen != sizeof(iremotes)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ memcpy(&iremotes, imsg.data, sizeof(iremotes));
+ if (iremotes.nremotes == 0) {
+ imsg_free(&imsg);
+ return NULL;
+ }
break;
default:
err = got_error(GOT_ERR_PRIVSEP_MSG);
}
imsg_free(&imsg);
+
+ *remotes = recallocarray(NULL, 0, iremotes.nremotes, sizeof(iremote));
+ if (*remotes == NULL)
+ return got_error_from_errno("recallocarray");
+
+ while (*nremotes < iremotes.nremotes) {
+ struct got_remote_repo *remote;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, sizeof(iremote));
+ if (err)
+ break;
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_GITCONFIG_REMOTE:
+ remote = &(*remotes)[*nremotes];
+ if (datalen < sizeof(iremote)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ memcpy(&iremote, imsg.data, sizeof(iremote));
+ if (iremote.name_len == 0 || iremote.url_len == 0 ||
+ (sizeof(iremote) + iremote.name_len +
+ iremote.url_len) > datalen) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ remote->name = strndup(imsg.data + sizeof(iremote),
+ iremote.name_len);
+ if (remote->name == NULL) {
+ err = got_error_from_errno("strndup");
+ break;
+ }
+ remote->url = strndup(imsg.data + sizeof(iremote) +
+ iremote.name_len, iremote.url_len);
+ if (remote->url == NULL) {
+ err = got_error_from_errno("strndup");
+ free(remote->name);
+ break;
+ }
+ (*nremotes)++;
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ imsg_free(&imsg);
+ if (err)
+ break;
+ }
+
+ if (err) {
+ int i;
+ for (i = 0; i < *nremotes; i++) {
+ free((*remotes)[i].name);
+ free((*remotes)[i].url);
+ }
+ free(*remotes);
+ *remotes = NULL;
+ *nremotes = 0;
+ }
return err;
}
blob - a5b0f8fded6c31a6c08dace849ceda974c1ef3c8
blob + e7022555ae9106a6b519d797cb9e28bbdfe897b4
--- lib/repository.c
+++ lib/repository.c
if (*p == NULL)
return got_error_from_errno("asprintf");
return NULL;
+}
+
+void
+got_repo_get_gitconfig_remotes(int *nremotes, struct got_remote_repo **remotes,
+ struct got_repository *repo)
+{
+ *nremotes = repo->ngitconfig_remotes;
+ *remotes = repo->gitconfig_remotes;
}
static int
static const struct got_error *
parse_gitconfig_file(int *gitconfig_repository_format_version,
char **gitconfig_author_name, char **gitconfig_author_email,
+ struct got_remote_repo **remotes, int *nremotes,
const char *gitconfig_path)
{
const struct got_error *err = NULL, *child_err = NULL;
err = got_privsep_recv_gitconfig_str(gitconfig_author_email, ibuf);
if (err)
goto done;
+
+ if (remotes && nremotes) {
+ err = got_privsep_send_gitconfig_remotes_req(ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_recv_gitconfig_remotes(remotes,
+ nremotes, ibuf);
+ if (err)
+ goto done;
+ }
imsg_clear(ibuf);
err = got_privsep_send_stop(imsg_fds[0]);
err = parse_gitconfig_file(&dummy_repo_version,
&repo->global_gitconfig_author_name,
&repo->global_gitconfig_author_email,
- global_gitconfig_path);
+ NULL, NULL, global_gitconfig_path);
if (err)
return err;
}
err = parse_gitconfig_file(&repo->gitconfig_repository_format_version,
&repo->gitconfig_author_name, &repo->gitconfig_author_email,
+ &repo->gitconfig_remotes, &repo->ngitconfig_remotes,
repo_gitconfig_path);
if (err)
goto done;
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);
+ }
+ free(repo->gitconfig_remotes);
free(repo);
return err;
blob - c14f37dd21a67e7027328b8a776e99a036726c7c
blob + 7c6439deb2b6bd6dd54a308e07d765495636ca39
--- libexec/got-read-gitconfig/got-read-gitconfig.c
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
#include "got_error.h"
#include "got_object.h"
+#include "got_repository.h"
#include "got_lib_delta.h"
#include "got_lib_object.h"
return got_privsep_send_gitconfig_str(ibuf, value);
}
+static const struct got_error *
+gitconfig_remotes_request(struct imsgbuf *ibuf, struct got_gitconfig *gitconfig)
+{
+ const struct got_error *err = NULL;
+ struct got_gitconfig_list *sections;
+ struct got_gitconfig_list_node *node;
+ struct got_remote_repo *remotes = NULL;
+ int nremotes = 0, i;
+
+ if (gitconfig == NULL)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ err = got_gitconfig_get_section_list(§ions, gitconfig);
+ if (err)
+ return err;
+
+ TAILQ_FOREACH(node, §ions->fields, link) {
+ if (strncasecmp("remote \"", node->field, 8) != 0)
+ continue;
+ nremotes++;
+ }
+
+ if (nremotes == 0) {
+ err = got_privsep_send_gitconfig_remotes(ibuf, NULL, 0);
+ goto done;
+ }
+
+ remotes = recallocarray(NULL, 0, nremotes, sizeof(*remotes));
+ if (remotes == NULL) {
+ err = got_error_from_errno("recallocarray");
+ goto done;
+ }
+
+ i = 0;
+ TAILQ_FOREACH(node, §ions->fields, link) {
+ char *name, *end;
+
+ if (strncasecmp("remote \"", node->field, 8) != 0)
+ continue;
+
+ name = strdup(node->field + 8);
+ if (name == NULL) {
+ err = got_error_from_errno("strdup");
+ goto done;
+ }
+ end = strrchr(name, '"');
+ if (end)
+ *end = '\0';
+ remotes[i].name = name;
+
+ remotes[i].url = got_gitconfig_get_str(gitconfig,
+ node->field, "url");
+ if (remotes[i].url == NULL) {
+ err = got_error(GOT_ERR_GITCONFIG_SYNTAX);
+ goto done;
+ }
+
+ i++;
+ }
+
+ err = got_privsep_send_gitconfig_remotes(ibuf, remotes, nremotes);
+done:
+ for (i = 0; i < nremotes; i++)
+ free(remotes[i].name);
+ free(remotes);
+ got_gitconfig_free_list(sections);
+ return err;
+}
+
int
main(int argc, char *argv[])
{
err = gitconfig_str_request(&ibuf, gitconfig, "user",
"email");
break;
+ case GOT_IMSG_GITCONFIG_REMOTES_REQUEST:
+ err = gitconfig_remotes_request(&ibuf, gitconfig);
+ break;
default:
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;