commit - 4b55f4595673e9079751e4fe3365b412972a4c11
commit + aba9c984d1420b77b23320520e70b27ecc83acf7
blob - 8c1fca65ca8a824451198211eb32ae34620b0f8f
blob + 4d887779da3647bcf38fded4c8db1d120fb3aaaf
--- got/Makefile
+++ got/Makefile
object_idset.c object_parse.c opentemp.c path.c pack.c \
privsep.c reference.c repository.c sha1.c worktree.c \
inflate.c buf.c worklist.c rcsutil.c diff3.c lockfile.c \
- deflate.c object_create.c gitconfig.c
+ deflate.c object_create.c
MAN = ${PROG}.1 got-worktree.5 git-repository.5
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib
blob - 8ff5e0925c6e1d39cd9c22786a291f25996cb555
blob + ba35bfd0b7a92102f226ca60b973aafe8a4083e7
--- got/got.1
+++ got/got.1
.Cm got import
command requires the
.Ev GOT_AUTHOR
-environment variable to be set.
+environment variable to be set,
+unless Git's
+.Dv user.name
+and
+.Dv user.email configuration settings can be
+obtained from the repository's
+.Pa .git/config
+file.
.Pp
The options for
.Cm got import
.Cm got commit
command requires the
.Ev GOT_AUTHOR
-environment variable to be set.
+environment variable to be set,
+unless Git's
+.Dv user.name
+and
+.Dv user.email configuration settings can be
+obtained from the repository's
+.Pa .git/config
+file.
.Pp
The options for
.Cm got commit
and
.Cm got import ,
for example:
-.An Flan Hacker Aq Mt flan_hacker@openbsd.org .
+.Dq An Flan Hacker Aq Mt flan_hacker@openbsd.org .
Because
.Xr git 1
may fail to parse commits without an email address in author data,
attempts to reject
.Ev GOT_AUTHOR
environment variables with a missing email address.
+Git's
+.Dv user.name
+and
+.Dv user.email configuration settings in the repository's
+.Pa .git/config
+file will override the value of
+.Ev GOT_AUTHOR .
.It Ev VISUAL , EDITOR
The editor spawned by
.Cm got commit ,
blob - 4c8177b93f67a544c333230c5af5ce699c45e6ab
blob + 5f3779846731a64630d792b8c821b712956c9160
--- got/got.c
+++ got/got.c
}
static const struct got_error *
-get_author(const char **author)
+get_author(char **author, struct got_repository *repo)
{
- const char *got_author;
+ const struct got_error *err = NULL;
+ const char *got_author, *gitconfig_name, *gitconfig_email;
*author = NULL;
+
+ gitconfig_name = got_repo_get_gitconfig_author_name(repo);
+ gitconfig_email = got_repo_get_gitconfig_author_email(repo);
+ if (gitconfig_name && gitconfig_email) {
+ if (asprintf(author, "%s <%s>",
+ gitconfig_name, gitconfig_email) == -1)
+ return got_error_from_errno("asprintf");
+ return NULL;
+ }
got_author = getenv("GOT_AUTHOR");
if (got_author == NULL) {
return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
}
- *author = got_author;
+ *author = strdup(got_author);
+ if (*author == NULL)
+ return got_error_from_errno("strdup");
/*
* Really dumb email address check; we're only doing this to
*/
while (*got_author && *got_author != '<')
got_author++;
- if (*got_author != '<')
- return got_error(GOT_ERR_COMMIT_NO_EMAIL);
+ if (*got_author != '<') {
+ err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
+ goto done;
+ }
while (*got_author && *got_author != '@')
got_author++;
- if (*got_author != '@')
- return got_error(GOT_ERR_COMMIT_NO_EMAIL);
+ if (*got_author != '@') {
+ err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
+ goto done;
+ }
while (*got_author && *got_author != '>')
got_author++;
if (*got_author != '>')
- return got_error(GOT_ERR_COMMIT_NO_EMAIL);
-
- return NULL;
+ err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
+done:
+ if (err) {
+ free(*author);
+ *author = NULL;
+ }
+ return err;
}
static const struct got_error *
{
const struct got_error *error = NULL;
char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
- char *editor = NULL;
- const char *author;
+ char *editor = NULL, *author = NULL;
const char *branch_name = "master";
char *refname = NULL, *id_str = NULL;
struct got_repository *repo = NULL;
argv += optind;
#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath fattr flock proc exec unveil",
+ if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
+ "unveil",
NULL) == -1)
err(1, "pledge");
#endif
if (argc != 1)
usage_import();
-
- error = get_author(&author);
- if (error)
- return error;
if (repo_path == NULL) {
repo_path = getcwd(NULL, 0);
error = got_repo_open(&repo, repo_path);
if (error)
goto done;
+
+ error = get_author(&author, repo);
+ if (error)
+ return error;
if (asprintf(&refname, "refs/heads/%s", branch_name) == -1) {
error = got_error_from_errno("asprintf");
free(refname);
free(new_commit_id);
free(id_str);
+ free(author);
if (branch_ref)
got_ref_close(branch_ref);
if (head_ref)
struct got_object_id *commit_id = NULL, *tag_id = NULL;
char *label = NULL, *commit_id_str = NULL;
struct got_reference *ref = NULL;
- char *refname = NULL, *tagmsg = NULL;
- const char *tagger;
+ char *refname = NULL, *tagmsg = NULL, *tagger = NULL;
/*
* Don't let the user create a tag named '-'.
if (tag_name[0] == '-' && tag_name[1] == '\0')
return got_error(GOT_ERR_BAD_REF_NAME);
- err = get_author(&tagger);
+ err = get_author(&tagger, repo);
if (err)
return err;
free(commit_id_str);
free(refname);
free(tagmsg);
+ free(tagger);
return err;
}
char *cwd = NULL, *id_str = NULL;
struct got_object_id *id = NULL;
const char *logmsg = NULL;
- const char *author;
- struct collect_commit_logmsg_arg cl_arg;
- char *editor = NULL;
+ struct collect_commit_logmsg_arg cl_arg;
+ char *editor = NULL, *author = NULL;
int ch, rebase_in_progress, histedit_in_progress;
struct got_pathlist_head paths;
"unveil", NULL) == -1)
err(1, "pledge");
#endif
- error = get_author(&author);
- if (error)
- return error;
-
cwd = getcwd(NULL, 0);
if (cwd == NULL) {
error = got_error_from_errno("getcwd");
if (error != NULL)
goto done;
+ error = get_author(&author, repo);
+ if (error)
+ return error;
+
/*
* unveil(2) traverses exec(2); if an editor is used we have
* to apply unveil after the log message has been written.
free(cwd);
free(id_str);
free(editor);
+ free(author);
return error;
}
blob - 97f04731b6ad9e1bccd53406696dab9612512659
blob + f8e9822b47d297dd837ffbfe9f018be2143c3b44
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_PATCH_CHOICE 107
#define GOT_ERR_COMMIT_NO_EMAIL 108
#define GOT_ERR_TAG_EXISTS 109
+#define GOT_ERR_GIT_REPO_FORMAT 110
static const struct got_error {
int code;
"no email address; an email address is required for compatibility "
"with Git" },
{ GOT_ERR_TAG_EXISTS,"specified tag already exists" },
+ { GOT_ERR_GIT_REPO_FORMAT,"unknown git repository format version" },
};
/*
blob - 16cdca51a48b0e15d4516534fe4efec46fe384af
blob + f2ecc7472a8da5185c853683082cf7806c36d290
--- include/got_repository.h
+++ include/got_repository.h
*/
const char *got_repo_get_path_git_dir(struct got_repository *);
+/* Obtain the commit author name if parsed from gitconfig, else NULL. */
+const char *got_repo_get_gitconfig_author_name(struct got_repository *);
+
+/* Obtain the commit author email if parsed from gitconfig, else NULL. */
+const char *got_repo_get_gitconfig_author_email(struct got_repository *);
+
/*
* Obtain paths to various directories within a repository.
* The caller must dispose of a path with free(3).
blob - 754cbc5403b1c92e536fca4f373dea3a300c73d4
blob + 1ddfb97d543989190d1cf894c45ed4ed1424f1aa
--- lib/gitconfig.c
+++ lib/gitconfig.c
}
const struct got_error *
-got_gitconfig_open(struct got_gitconfig **conf, const char *gitconfig_path)
+got_gitconfig_open(struct got_gitconfig **conf, int fd)
{
unsigned int i;
for (i = 0; i < nitems((*conf)->bindings); i++)
LIST_INIT(&(*conf)->bindings[i]);
TAILQ_INIT(&(*conf)->trans_queue);
- return got_gitconfig_reinit(*conf, gitconfig_path);
+ return got_gitconfig_reinit(*conf, fd);
}
static void
/* Open the config file and map it into our address space, then parse it. */
const struct got_error *
-got_gitconfig_reinit(struct got_gitconfig *conf, const char *gitconfig_path)
+got_gitconfig_reinit(struct got_gitconfig *conf, int fd)
{
const struct got_error *err = NULL;
- int fd, trans;
+ int trans;
size_t sz;
char *new_conf_addr = 0;
struct stat st;
- fd = open(gitconfig_path, O_RDONLY, 0);
- if (fd == -1) {
- if (errno != ENOENT)
- return got_error_from_errno2("open", gitconfig_path);
- return NULL;
- }
-
if (fstat(fd, &st)) {
- err = got_error_from_errno2("fstat", gitconfig_path);
+ err = got_error_from_errno("fstat");
goto fail;
}
err = got_error_from_errno("read");
goto fail;
}
- close(fd);
- fd = -1;
trans = conf_begin(conf);
fail:
free(new_conf_addr);
- if (fd != -1)
- close(fd);
return err;
}
blob - 828787b0e4bac8fc800346d343d9896bcd3e3801
blob + 4d61ab3964722d849b94e3048f1cb6a15d2edc3f
--- lib/got_lib_gitconfig.h
+++ lib/got_lib_gitconfig.h
struct got_gitconfig;
void got_gitconfig_free_list(struct got_gitconfig_list *);
-struct got_gitconfig_list *got_gitconfig_get_list(struct got_gitconfig *, char *, char *);
+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 *);
-int got_gitconfig_get_num(struct got_gitconfig *, char *, char *, int);
-char *got_gitconfig_get_str(struct got_gitconfig *, char *, char *);
-const struct got_error *got_gitconfig_open(struct got_gitconfig **,
- const char *);
+int got_gitconfig_get_num(struct got_gitconfig *, char *, char *,
+ int);
+char *got_gitconfig_get_str(struct got_gitconfig *, char *,
+ char *);
+const struct got_error *got_gitconfig_open(struct got_gitconfig **, int);
void got_gitconfig_close(struct got_gitconfig *);
int got_gitconfig_match_num(struct got_gitconfig *, char *, char *, int);
-const struct got_error *got_gitconfig_reinit(struct got_gitconfig *, const char *);
+const struct got_error *got_gitconfig_reinit(struct got_gitconfig *, int);
int got_gitconfig_remove(struct got_gitconfig *, int, char *, char *);
int got_gitconfig_remove_section(struct got_gitconfig *, int, char *);
int got_gitconfig_set(struct got_gitconfig *, int, char *, char *, char *, int, int);
blob - 1ad8832b391a09f83bd2201d0c1400a6c47b6f39
blob + f1e7f2ad14684a954b1bc1e9b4a6195cc963c7c3
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
#define GOT_PROG_READ_BLOB got-read-blob
#define GOT_PROG_READ_TAG got-read-tag
#define GOT_PROG_READ_PACK got-read-pack
+#define GOT_PROG_READ_GITCONFIG got-read-gitconfig
#define GOT_STRINGIFY(x) #x
#define GOT_STRINGVAL(x) GOT_STRINGIFY(x)
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_TAG)
#define GOT_PATH_PROG_READ_PACK \
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_PACK)
+#define GOT_PATH_PROG_READ_GITCONFIG \
+ GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_GITCONFIG)
struct got_privsep_child {
int imsg_fd;
/* Message sending file descriptor to a temporary file. */
GOT_IMSG_TMPFD,
+
+ /* Messages related to gitconfig files. */
+ GOT_IMSG_GITCONFIG_PARSE_REQUEST,
+ GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST,
+ GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST,
+ GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST,
+ GOT_IMSG_GITCONFIG_INT_VAL,
+ GOT_IMSG_GITCONFIG_STR_VAL,
};
/* Structure for GOT_IMSG_ERROR. */
const struct got_error *got_privsep_send_packed_obj_req(struct imsgbuf *, int,
struct got_object_id *);
const struct got_error *got_privsep_send_pack_child_ready(struct imsgbuf *);
+
+const struct got_error *got_privsep_send_gitconfig_parse_req(struct imsgbuf *,
+ int);
+const struct got_error *
+ got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *);
+const struct got_error *got_privsep_send_gitconfig_author_name_req(
+ struct imsgbuf *);
+const struct got_error *got_privsep_send_gitconfig_author_email_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 *);
+
+void got_privsep_exec_child(int[2], const char *, const char *);
blob - 23ca2d585f593cbd7176990ce665928bea219089
blob + 71d6c0578341427205b4086dc64fde982ec030e4
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
struct got_object_cache tagcache;
/* Settings read from Git configuration files. */
- struct got_gitconfig *gitconfig;
+ int gitconfig_repository_format_version;
+ char *gitconfig_author_name;
+ char *gitconfig_author_email;
};
const struct got_error*got_repo_cache_object(struct got_repository *,
blob - e5c043ce567c8eb883622b2a78b71bb9ba64227d
blob + ca9b1470b78030edb637ec17878e01fe010a17b1
--- lib/object.c
+++ lib/object.c
return got_error(GOT_ERR_NO_SPACE);
return NULL;
-}
-
-static void
-exec_privsep_child(int imsg_fds[2], const char *path, const char *repo_path)
-{
- if (close(imsg_fds[0]) != 0) {
- fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
- _exit(1);
- }
-
- if (dup2(imsg_fds[1], GOT_IMSG_FD_CHILD) == -1) {
- fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
- _exit(1);
- }
- if (closefrom(GOT_IMSG_FD_CHILD + 1) == -1) {
- fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
- _exit(1);
- }
-
- if (execl(path, path, repo_path, (char *)NULL) == -1) {
- fprintf(stderr, "%s: %s: %s\n", getprogname(), path,
- strerror(errno));
- _exit(1);
- }
}
static const struct got_error *
goto done;
} else if (pid == 0) {
set_max_datasize();
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_PACK,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_PACK,
pack->path_packfile);
/* not reached */
}
if (pid == -1)
return got_error_from_errno("fork");
else if (pid == 0) {
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_OBJECT,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_OBJECT,
repo->path);
/* not reached */
}
if (pid == -1)
return got_error_from_errno("fork");
else if (pid == 0) {
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_COMMIT,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_COMMIT,
repo->path);
/* not reached */
}
if (pid == -1)
return got_error_from_errno("fork");
else if (pid == 0) {
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_TREE,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_TREE,
repo->path);
/* not reached */
}
if (pid == -1)
return got_error_from_errno("fork");
else if (pid == 0) {
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_BLOB,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_BLOB,
repo->path);
/* not reached */
}
if (pid == -1)
return got_error_from_errno("fork");
else if (pid == 0) {
- exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_TAG,
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_TAG,
repo->path);
/* not reached */
}
blob - f1ce37f56adc95e212cca7ec18ec0d69629deac9
blob + f9961bfb6a787156474e30da32622cdb054366e6
--- lib/privsep.c
+++ lib/privsep.c
&iobj, sizeof(iobj)) == -1)
return got_error_from_errno("imsg_compose "
"PACKED_OBJECT_REQUEST");
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_parse_req(struct imsgbuf *ibuf, int fd)
+{
+ const struct got_error *err = NULL;
+
+ if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_PARSE_REQUEST, 0, 0, fd,
+ NULL, 0) == -1) {
+ err = got_error_from_errno("imsg_compose "
+ "GITCONFIG_PARSE_REQUEST");
+ close(fd);
+ return err;
+ }
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *ibuf)
+{
+ if (imsg_compose(ibuf,
+ GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST, 0, 0, -1,
+ NULL, 0) == -1)
+ return got_error_from_errno("imsg_compose "
+ "GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST");
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_author_name_req(struct imsgbuf *ibuf)
+{
+ if (imsg_compose(ibuf,
+ GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST, 0, 0, -1, NULL, 0) == -1)
+ return got_error_from_errno("imsg_compose "
+ "GITCONFIG_AUTHOR_NAME_REQUEST");
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_author_email_req(struct imsgbuf *ibuf)
+{
+ if (imsg_compose(ibuf,
+ 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_str(struct imsgbuf *ibuf, const char *value)
+{
+ size_t len = value ? strlen(value) + 1 : 0;
+
+ if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_STR_VAL, 0, 0, -1,
+ value, len) == -1)
+ return got_error_from_errno("imsg_compose GITCONFIG_STR_VAL");
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_recv_gitconfig_str(char **str, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ size_t datalen;
+ const size_t min_datalen = 0;
+
+ *str = NULL;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
+ if (err)
+ return err;
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_GITCONFIG_STR_VAL:
+ if (datalen == 0)
+ break;
+ *str = malloc(datalen);
+ if (*str == NULL) {
+ err = got_error_from_errno("malloc");
+ break;
+ }
+ if (strlcpy(*str, imsg.data, datalen) >= datalen)
+ err = got_error(GOT_ERR_NO_SPACE);
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ imsg_free(&imsg);
+ return err;
+}
+
+const struct got_error *
+got_privsep_send_gitconfig_int(struct imsgbuf *ibuf, int value)
+{
+ if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_INT_VAL, 0, 0, -1,
+ &value, sizeof(value)) == -1)
+ return got_error_from_errno("imsg_compose GITCONFIG_INT_VAL");
+
return flush_imsg(ibuf);
}
const struct got_error *
+got_privsep_recv_gitconfig_int(int *val, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ size_t datalen;
+ const size_t min_datalen =
+ MIN(sizeof(struct got_imsg_error), sizeof(int));
+
+ *val = 0;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
+ if (err)
+ return err;
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_GITCONFIG_INT_VAL:
+ if (datalen != sizeof(*val)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ 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_unveil_exec_helpers(void)
{
const char *helpers[] = {
GOT_PATH_PROG_READ_TREE,
GOT_PATH_PROG_READ_BLOB,
GOT_PATH_PROG_READ_TAG,
+ GOT_PATH_PROG_READ_GITCONFIG,
};
int i;
return NULL;
}
+
+void
+got_privsep_exec_child(int imsg_fds[2], const char *path, const char *repo_path)
+{
+ if (close(imsg_fds[0]) != 0) {
+ fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
+ _exit(1);
+ }
+
+ if (dup2(imsg_fds[1], GOT_IMSG_FD_CHILD) == -1) {
+ fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
+ _exit(1);
+ }
+ if (closefrom(GOT_IMSG_FD_CHILD + 1) == -1) {
+ fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
+ _exit(1);
+ }
+
+ if (execl(path, path, repo_path, (char *)NULL) == -1) {
+ fprintf(stderr, "%s: %s: %s\n", getprogname(), path,
+ strerror(errno));
+ _exit(1);
+ }
+}
blob - dbee69ba57b1497c455672f6741600c07c1f5af1
blob + 454319ad653bfd26ee86f6f74aa4302c19018868
--- lib/repository.c
+++ lib/repository.c
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/uio.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/syslimits.h>
#include "got_lib_sha1.h"
#include "got_lib_object_cache.h"
#include "got_lib_repository.h"
-#include "got_lib_gitconfig.h"
#ifndef nitems
#define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
return repo->path_git_dir;
}
+const char *
+got_repo_get_gitconfig_author_name(struct got_repository *repo)
+{
+ return repo->gitconfig_author_name;
+}
+
+/* Obtain the commit author email address parsed from gitconfig. */
+const char *
+got_repo_get_gitconfig_author_email(struct got_repository *repo)
+{
+ return repo->gitconfig_author_email;
+}
+
int
got_repo_is_bare(struct got_repository *repo)
{
repo->path = NULL;
free(repo->path_git_dir);
repo->path_git_dir = NULL;
+ }
+ return err;
+}
+
+static const struct got_error *
+read_gitconfig(struct got_repository *repo)
+{
+ const struct got_error *err = NULL, *child_err = NULL;
+ char *gitconfig_path = NULL;
+ int fd = -1;
+ int imsg_fds[2] = { -1, -1 };
+ pid_t pid;
+ struct imsgbuf *ibuf;
+
+ /* TODO: Read settings from ~/.gitconfig as well? */
+
+ /* Read repository's .git/config file. */
+ err = get_path_gitconfig(&gitconfig_path, repo);
+ if (err)
+ return err;
+
+ fd = open(gitconfig_path, O_RDONLY);
+ if (fd == -1) {
+ if (errno == ENOENT) {
+ free(gitconfig_path);
+ return NULL;
+ }
+ err = got_error_from_errno2("open", gitconfig_path);
+ free(gitconfig_path);
+ return err;
+ }
+
+ ibuf = calloc(1, sizeof(*ibuf));
+ if (ibuf == NULL) {
+ err = got_error_from_errno("calloc");
+ goto done;
+ }
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1) {
+ err = got_error_from_errno("socketpair");
+ goto done;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ err = got_error_from_errno("fork");
+ goto done;
+ } else if (pid == 0) {
+ got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_GITCONFIG,
+ repo->path);
+ /* not reached */
+ }
+
+ if (close(imsg_fds[1]) == -1) {
+ err = got_error_from_errno("close");
+ goto done;
}
+ imsg_fds[1] = -1;
+ imsg_init(ibuf, imsg_fds[0]);
+
+ err = got_privsep_send_gitconfig_parse_req(ibuf, fd);
+ if (err)
+ goto done;
+ fd = -1;
+
+ err = got_privsep_send_gitconfig_repository_format_version_req(ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_recv_gitconfig_int(
+ &repo->gitconfig_repository_format_version, ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_send_gitconfig_author_name_req(ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_recv_gitconfig_str(&repo->gitconfig_author_name,
+ ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_send_gitconfig_author_email_req(ibuf);
+ if (err)
+ goto done;
+
+ err = got_privsep_recv_gitconfig_str(&repo->gitconfig_author_email,
+ ibuf);
+ if (err)
+ goto done;
+
+ imsg_clear(ibuf);
+ err = got_privsep_send_stop(imsg_fds[0]);
+ child_err = got_privsep_wait_for_child(pid);
+ if (child_err && err == NULL)
+ err = child_err;
+done:
+ if (imsg_fds[0] != -1 && close(imsg_fds[0]) == -1 && err == NULL)
+ err = got_error_from_errno("close");
+ if (imsg_fds[1] != -1 && close(imsg_fds[1]) == -1 && err == NULL)
+ err = got_error_from_errno("close");
+ if (fd != -1 && close(fd) == -1 && err == NULL)
+ err = got_error_from_errno2("close", gitconfig_path);
+ free(gitconfig_path);
+ free(ibuf);
return err;
}
{
struct got_repository *repo = NULL;
const struct got_error *err = NULL;
- char *abspath, *gitconfig_path = NULL;
+ char *abspath;
int i, tried_root = 0;
*repop = NULL;
}
} while (path);
- err = get_path_gitconfig(&gitconfig_path, repo);
+ err = read_gitconfig(repo);
if (err)
goto done;
-
-#ifdef notyet
- err = got_gitconfig_open(&repo->gitconfig, gitconfig_path);
- if (err)
- goto done;
-#else
- repo->gitconfig = NULL;
-#endif
+ if (repo->gitconfig_repository_format_version != 0)
+ err = got_error_path(path, GOT_ERR_GIT_REPO_FORMAT);
done:
if (err)
got_repo_close(repo);
else
*repop = repo;
free(abspath);
- free(gitconfig_path);
return err;
}
err == NULL)
err = got_error_from_errno("close");
}
- if (repo->gitconfig)
- got_gitconfig_close(repo->gitconfig);
+
+ free(repo->gitconfig_author_name);
+ free(repo->gitconfig_author_email);
free(repo);
return err;
blob - f56d5677dd571b5ac1902a52d0f39389be75da6f
blob + a4c900b7f50d8d643524becc373f46951d405243
--- libexec/Makefile
+++ libexec/Makefile
SUBDIR = got-read-blob got-read-commit got-read-object got-read-tree \
- got-read-tag got-read-pack
+ got-read-tag got-read-pack got-read-gitconfig
.include <bsd.subdir.mk>
blob - /dev/null
blob + f49bf06548491001d3b2fbc4da15ac568171dc17 (mode 644)
--- /dev/null
+++ libexec/got-read-gitconfig/Makefile
+.PATH:${.CURDIR}/../../lib
+
+.include "../../got-version.mk"
+
+PROG= got-read-gitconfig
+SRCS= got-read-gitconfig.c error.c inflate.c object_parse.c \
+ path.c privsep.c sha1.c gitconfig.c
+
+CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
+LDADD = -lutil -lz
+DPADD = ${LIBZ} ${LIBUTIL}
+
+.include <bsd.prog.mk>
blob - /dev/null
blob + c14f37dd21a67e7027328b8a776e99a036726c7c (mode 644)
--- /dev/null
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
+/*
+ * Copyright (c) 2019 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/syslimits.h>
+
+#include <stdint.h>
+#include <imsg.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sha1.h>
+#include <zlib.h>
+
+#include "got_error.h"
+#include "got_object.h"
+
+#include "got_lib_delta.h"
+#include "got_lib_object.h"
+#include "got_lib_privsep.h"
+#include "got_lib_gitconfig.h"
+
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
+static const struct got_error *
+gitconfig_num_request(struct imsgbuf *ibuf, struct got_gitconfig *gitconfig,
+ char *section, char *tag, int def)
+{
+ int value;
+
+ if (gitconfig == NULL)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ value = got_gitconfig_get_num(gitconfig, section, tag, def);
+ return got_privsep_send_gitconfig_int(ibuf, value);
+}
+
+static const struct got_error *
+gitconfig_str_request(struct imsgbuf *ibuf, struct got_gitconfig *gitconfig,
+ char *section, char *tag)
+{
+ char *value;
+
+ if (gitconfig == NULL)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ value = got_gitconfig_get_str(gitconfig, section, tag);
+ return got_privsep_send_gitconfig_str(ibuf, value);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const struct got_error *err = NULL;
+ struct imsgbuf ibuf;
+ size_t datalen;
+ struct got_gitconfig *gitconfig = NULL;
+#if 0
+ static int attached;
+
+ while (!attached)
+ sleep(1);
+#endif
+ signal(SIGINT, catch_sigint);
+
+ imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
+
+#ifndef PROFILE
+ /* revoke access to most system calls */
+ if (pledge("stdio recvfd", NULL) == -1) {
+ err = got_error_from_errno("pledge");
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
+#endif
+
+ for (;;) {
+ struct imsg imsg;
+
+ memset(&imsg, 0, sizeof(imsg));
+ imsg.fd = -1;
+
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
+
+ err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
+ if (err) {
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ break;
+ }
+
+ if (imsg.hdr.type == GOT_IMSG_STOP)
+ break;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_GITCONFIG_PARSE_REQUEST:
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != 0) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ if (imsg.fd == -1){
+ err = got_error(GOT_ERR_PRIVSEP_NO_FD);
+ break;
+ }
+
+ if (gitconfig)
+ got_gitconfig_close(gitconfig);
+ err = got_gitconfig_open(&gitconfig, imsg.fd);
+ break;
+ case GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST:
+ err = gitconfig_num_request(&ibuf, gitconfig, "core",
+ "repositoryformatversion", 0);
+ break;
+ case GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST:
+ err = gitconfig_str_request(&ibuf, gitconfig, "user",
+ "name");
+ break;
+ case GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST:
+ err = gitconfig_str_request(&ibuf, gitconfig, "user",
+ "email");
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ if (imsg.fd != -1) {
+ if (close(imsg.fd) == -1 && err == NULL)
+ err = got_error_from_errno("close");
+ }
+
+ imsg_free(&imsg);
+ if (err)
+ break;
+ }
+
+ imsg_clear(&ibuf);
+ if (err) {
+ if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE) {
+ fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ got_privsep_send_error(&ibuf, err);
+ }
+ }
+ if (close(GOT_IMSG_FD_CHILD) != 0 && err == NULL)
+ err = got_error_from_errno("close");
+ return err ? 1 : 0;
+}
blob - 451b7e6f6979220b6f28c544d8bac7eeb6380112
blob + 55340c74b234a5573505c25f1137cc947e5d43d5
--- regress/cmdline/commit.sh
+++ regress/cmdline/commit.sh
ret="$?"
test_done "$testroot" "$ret"
}
+
+function test_commit_gitconfig_author {
+ local testroot=`test_init commit_gitconfig_author`
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/repo && git config user.name 'Flan Luck')
+ (cd $testroot/repo && git config user.email 'flan_luck@openbsd.org')
+
+ echo "modified alpha" > $testroot/wt/alpha
+ (cd $testroot/wt && got commit -m 'test gitconfig author' > /dev/null)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/repo && got log -l1 | grep ^from: > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "from: Flan Luck <flan_luck@openbsd.org>" \
+ > $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
run_test test_commit_basic
run_test test_commit_new_subdir
run_test test_commit_subdir
run_test test_commit_outside_refs_heads
run_test test_commit_no_email
run_test test_commit_tree_entry_sorting
+run_test test_commit_gitconfig_author
blob - c4fa14f3feb7a9f4a7b01276e5b724b478cab932
blob + 85f9a8965833c7ec25df706646762df09e50327b
--- tog/Makefile
+++ tog/Makefile
object_idset.c object_parse.c opentemp.c path.c pack.c \
privsep.c reference.c repository.c sha1.c worktree.c \
utf8.c inflate.c buf.c worklist.c rcsutil.c diff3.c \
- lockfile.c deflate.c object_create.c gitconfig.c
+ lockfile.c deflate.c object_create.c
MAN = ${PROG}.1
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib