Download raw body.
draft: keeping authorship of diffs in commits
Hello, Although it's not really used on OpenBSD (because one lists OKs and such in the commit message), when working on personal projects I'd like to keep the authorship of diffs I receive. With git the usual workflow is to receive a git-formatted patch (e.g. via git send-email) and apply it locally with git-am. git-am is able to extract the author of the patch from the email and use it in the commit. That's the "from" and "via" fields showed by tog. Got only allows to set the author of the commit (the "from" field in tog) but not the committer of the diff. In the past I've set GOT_AUTHOR before committing to the username and email of the author of the diff. While viable, that doesn't set the committer ("via" field in tog). OK, it's a bit of an aesthetic reason, but I'd like to being able to keep the authorship and still be listed as the committer of a diff. Diff below is a draft for this. It lacks several things (manpage bits, testing, probably more) and it also produces the wrong error message if -A has a wrong format, but it's just to gauge the interest and see if it's worth going forward. It adds an -A flag for got commit which is then used to set the author of the commit. The committer is still chosen the same way as always (got.conf, GOT_AUTHOR, ...) Cheers Omar Polo diff 4cd2c1745cda66c359c86bea412d77af0b643a7e /home/op/w/got blob - 16b939dba60d2210e6c75b2ffbb51a4b1f8d608a file + got/got.c --- got/got.c +++ got/got.c @@ -597,6 +597,28 @@ import_progress(void *arg, const char *path) } static const struct got_error * +validate_author(const char *author) +{ + /* + * Really dumb email address check; we're only doing this to + * avoid git's object parser breaking on commits we create. + */ + while (*author && *author != '<') + author++; + if (*author != '<') + return got_error(GOT_ERR_COMMIT_NO_EMAIL); + while (*author && *author != '@') + author++; + if (*author != '@') + return got_error(GOT_ERR_COMMIT_NO_EMAIL); + while (*author && *author != '>') + author++; + if (*author != '>') + return got_error(GOT_ERR_COMMIT_NO_EMAIL); + return NULL; +} + +static const struct got_error * get_author(char **author, struct got_repository *repo, struct got_worktree *worktree) { @@ -653,27 +675,7 @@ get_author(char **author, struct got_repository *repo, if (*author == NULL) return got_error_from_errno("strdup"); - /* - * Really dumb email address check; we're only doing this to - * avoid git's object parser breaking on commits we create. - */ - while (*got_author && *got_author != '<') - got_author++; - if (*got_author != '<') { - err = got_error(GOT_ERR_COMMIT_NO_EMAIL); - goto done; - } - while (*got_author && *got_author != '@') - got_author++; - if (*got_author != '@') { - err = got_error(GOT_ERR_COMMIT_NO_EMAIL); - goto done; - } - while (*got_author && *got_author != '>') - got_author++; - if (*got_author != '>') - err = got_error(GOT_ERR_COMMIT_NO_EMAIL); -done: + err = validate_author(got_author); if (err) { free(*author); *author = NULL; @@ -7528,8 +7530,9 @@ cmd_commit(int argc, char *argv[]) struct got_object_id *id = NULL; const char *logmsg = NULL; char *prepared_logmsg = NULL; + const char *author = NULL; struct collect_commit_logmsg_arg cl_arg; - char *gitconfig_path = NULL, *editor = NULL, *author = NULL; + char *gitconfig_path = NULL, *editor = NULL, *committer = NULL; int ch, rebase_in_progress, histedit_in_progress, preserve_logmsg = 0; int allow_bad_symlinks = 0, non_interactive = 0, merge_in_progress = 0; struct got_pathlist_head paths; @@ -7537,8 +7540,13 @@ cmd_commit(int argc, char *argv[]) TAILQ_INIT(&paths); cl_arg.logmsg_path = NULL; - while ((ch = getopt(argc, argv, "F:m:NS")) != -1) { + while ((ch = getopt(argc, argv, "A:F:m:NS")) != -1) { switch (ch) { + case 'A': + author = optarg; + if ((error = validate_author(author)) != NULL) + return error; + break; case 'F': if (logmsg != NULL) option_conflict('F', 'm'); @@ -7613,9 +7621,11 @@ cmd_commit(int argc, char *argv[]) goto done; } - error = get_author(&author, repo, worktree); + error = get_author(&committer, repo, worktree); if (error) return error; + if (author == NULL) + author = committer; /* * unveil(2) traverses exec(2); if an editor is used we have @@ -7647,7 +7657,7 @@ cmd_commit(int argc, char *argv[]) cl_arg.branch_name += 11; } cl_arg.repo_path = got_repo_get_path(repo); - error = got_worktree_commit(&id, worktree, &paths, author, NULL, + error = got_worktree_commit(&id, worktree, &paths, author, committer, allow_bad_symlinks, collect_commit_logmsg, &cl_arg, print_status, NULL, repo); if (error) { @@ -7680,7 +7690,7 @@ done: free(id_str); free(gitconfig_path); free(editor); - free(author); + free(committer); free(prepared_logmsg); return error; }
draft: keeping authorship of diffs in commits