commit - d54d17c383642334e7730bc2f9aa81d26c2df9ce
commit + 18d1acaddba2a6012509c2de642867984e27dbf4
blob - e40b2fea7364f818d1cc038e58b39c5e8b17968b
blob + 1500d062d6850b0c9d5a7a48b757ee6e54c05043
--- got/got.1
+++ got/got.1
is a directory.
.El
.Tg ci
-.It Cm commit Oo Fl F Ar path Oc Oo Fl m Ar message Oc Oo Fl N Oc Oo Fl S Oc Op Ar path ...
+.It Cm commit Oo Fl A Ar author Oc Oo Fl F Ar path Oc Oo Fl m Ar message Oc Oo Fl N Oc Oo Fl S Oc Op Ar path ...
.Dl Pq alias: Cm ci
Create a new commit in the repository from changes in a work tree
and use this commit as the new base commit for the work tree.
.Cm got commit
are as follows:
.Bl -tag -width Ds
+.It Fl A Ar author
+Set author information in the newly created commit to
+.Ar author .
+This is useful when committing changes which were written by someone
+else.
+The
+.Ar author
+argument must use the same format as the
+.Ev GOT_AUTHOR
+environment variable.
+.Pp
+In addition to storing author information, the newly created commit
+object will retain
+.Dq committer
+information which is obtained, as usual, from the
+.Ev GOT_AUTHOR
+environment variable, or
+.Xr got.conf 5 ,
+or Git configuration settings.
.It Fl F Ar path
Use the prepared log message stored in the file found at
.Ar path
blob - fdedddacfa4bbde46e722c1066f24c0ff20ab7b1
blob + 145cdfc9f538eb46011d799cb8da04757fa96fbf
--- got/got.c
+++ got/got.c
__dead static void
usage_commit(void)
{
- fprintf(stderr, "usage: %s commit [-F path] [-m msg] [-N] [-S] "
- "[path ...]\n", getprogname());
+ fprintf(stderr, "usage: %s commit [-A author] [-F path] [-m msg] "
+ "[-N] [-S] [path ...]\n", getprogname());
exit(1);
}
const char *logmsg = NULL;
char *prepared_logmsg = NULL;
struct collect_commit_logmsg_arg cl_arg;
- char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
+ const char *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;
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;
+ error = valid_author(author);
+ if (error)
+ return error;
+ break;
case 'F':
if (logmsg != NULL)
option_conflict('F', 'm');
goto done;
}
- error = get_author(&author, repo, worktree);
+ error = get_author(&committer, repo, worktree);
if (error)
return error;
+
+ if (author != NULL && !strcmp(committer, author)) {
+ error = got_error(GOT_ERR_COMMIT_REDUNDANT_AUTHOR);
+ goto done;
+ }
+
+ if (author == NULL)
+ author = committer;
/*
* unveil(2) traverses exec(2); if an editor is used we have
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) {
free(id_str);
free(gitconfig_path);
free(editor);
- free(author);
+ free(committer);
free(prepared_logmsg);
return error;
}
blob - 3f63bba02d14c1e32cb7499541ea9aa5c0dc9081
blob + ab13ceafe2a0043b913454118e0c81bab18d3ea1
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_BAD_TAG_SIGNATURE 154
#define GOT_ERR_VERIFY_TAG_SIGNATURE 155
#define GOT_ERR_SIGNING_TAG 156
+#define GOT_ERR_COMMIT_REDUNDANT_AUTHOR 157
struct got_error {
int code;
blob - 0b6349576da098cee9d587d219ed6b029456d568
blob + 210a973df2358f6e47727defc7f896614105a977
--- lib/error.c
+++ lib/error.c
{ GOT_ERR_BAD_TAG_SIGNATURE, "invalid tag signature" },
{ GOT_ERR_VERIFY_TAG_SIGNATURE, "cannot verify signature" },
{ GOT_ERR_SIGNING_TAG, "unable to sign tag" },
+ { GOT_ERR_COMMIT_REDUNDANT_AUTHOR, "specified author is equal to the "
+ "default one"},
};
static struct got_custom_error {
blob - cf2c3ea32defbab535ace771de28f684e7e74ff7
blob + 0b4639fa3e8e24f15cdb9d5e73a2334215eccff6
--- regress/cmdline/commit.sh
+++ regress/cmdline/commit.sh
> $testroot/fsck.stdout 2> $testroot/fsck.stderr)
ret=$?
test_done "$testroot" "$ret"
+}
+
+test_commit_cmdline_author() {
+ local testroot=`test_init commit_cmdline_author`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ echo "modified alpha" > $testroot/wt/alpha
+
+ # first try with a -A equals to $GOT_AUTHOR
+ (cd $testroot/wt && got commit -A "$GOT_AUTHOR" -m 'edit alpha') \
+ > /dev/null 2> $testroot/stderr
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ echo 'got: specified author is equal to the default one' \
+ > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ # try again with a different author
+ local author="Foo <foo@example.com>"
+ (cd $testroot/wt && got commit -A "$author" -m 'edit alpha') \
+ > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ (cd $testroot/repo && got log -l1 | egrep '^(from|via):') \
+ > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ echo "from: $author" > $testroot/stdout.expected
+ echo "via: $GOT_AUTHOR" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" $ret
}
test_commit_gotconfig_author() {
run_test test_commit_outside_refs_heads
run_test test_commit_no_email
run_test test_commit_tree_entry_sorting
+run_test test_commit_cmdline_author
run_test test_commit_gotconfig_author
run_test test_commit_gotconfig_worktree_author
run_test test_commit_gitconfig_author