"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
got histedit -m: edit log messages only
To:
gameoftrees@openbsd.org
Date:
Sun, 23 Feb 2020 16:29:18 +0100

Download raw body.

Thread
As is customary in OpenBSD we have been reviewing diffs on this list and
handing out OKs. However most commit messages in the got repo do not carry
this information, and that is bad.

Adding "OK someone" to log messages is already possible with 'got histedit',
but it is not as straightforward to use as e.g. git's 'commit --amend'.

With this new feature it becomes much easier and I think it is better than
git's concept because it allows adding OKs to all local commits, with one
command, before pushing them out.

All that's needed is backdating the work tree to the last common commit
(which will usually be origin/master) starting histedit in -m mode:

	got up -c origin/master
	got he -m

Does this make sense? Any suggestions or concerns?

diff dc990cbf2d39c406ff23bc36e6cbb822f747ee42 /home/stsp/src/got
blob - bfd42f09a78d05ccbb7abf0aed72286753e1ca73
file + got/got.1
--- got/got.1
+++ got/got.1
@@ -988,13 +988,17 @@ If this option is used, no other command-line argument
 .It Cm rb
 Short alias for
 .Cm rebase .
-.It Cm histedit Oo Fl a Oc Oo Fl c Oc Op Fl F Ar histedit-script
+.It Cm histedit Oo Fl a Oc Oo Fl c Oc Oo Fl F Ar histedit-script Oc Oo Fl m Oc
 Edit commit history between the work tree's current base commit and
 the tip commit of the work tree's current branch.
 .Pp
 Editing of commit history is controlled via a
 .Ar histedit script
-which can be edited interactively or passed on the command line.
+which can be edited interactively, passed on the command line,
+or generated with the
+.Fl m
+option if only log messages need to be edited.
+.Pp
 The format of the histedit script is line-based.
 Each line in the script begins with a command name, followed by
 whitespace and an argument.
@@ -1088,6 +1092,14 @@ If this option is used, no other command-line argument
 .It Fl c
 Continue an interrupted histedit operation.
 If this option is used, no other command-line arguments are allowed.
+.It Fl m
+Edit log messages only.
+This option is a quick equivalent to a histedit script which edits
+only log messages but otherwise uses every commit as-is.
+The
+.Fl m
+option can only be used when starting a new histedit operation.
+If this option is used, no other command-line arguments are allowed.
 .El
 .It Cm he
 Short alias for
@@ -1567,6 +1579,15 @@ This will also merge local changes, if any, with the i
 .Pp
 .Dl $ got update -b origin/master
 .Dl $ got rebase master
+.Pp
+On the
+.Dq master
+branch, log messages for local changes can now be amended with
+.Dq OK
+by other developers and any other important new information:
+.Pp
+.Dl $ got update -c origin/master
+.Dl $ got histedit -m
 .Pp
 Local changes on the
 .Dq master
blob - 4a5d5fcafa19f89e6039addb90f3c1979ea584e3
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -5561,7 +5561,7 @@ done:
 __dead static void
 usage_histedit(void)
 {
-	fprintf(stderr, "usage: %s histedit [-a] [-c] [-F histedit-script]\n",
+	fprintf(stderr, "usage: %s histedit [-a] [-c] [-F histedit-script] [-m]\n",
 	    getprogname());
 	exit(1);
 }
@@ -5627,8 +5627,8 @@ done:
 }
 
 static const struct got_error *
-histedit_write_commit_list(struct got_object_id_queue *commits, FILE *f,
-    struct got_repository *repo)
+histedit_write_commit_list(struct got_object_id_queue *commits,
+    FILE *f, int edit_logmsg_only, struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	struct got_object_qid *qid;
@@ -5641,6 +5641,13 @@ histedit_write_commit_list(struct got_object_id_queue 
 		    f, repo);
 		if (err)
 			break;
+		if (edit_logmsg_only) {
+			int n = fprintf(f, "%c\n", GOT_HISTEDIT_MESG);
+			if (n < 0) {
+				err = got_ferror(f, GOT_ERR_IO);
+				break;
+			}
+		}
 	}
 
 	return err;
@@ -6018,7 +6025,7 @@ histedit_edit_list_retry(struct got_histedit_list *, c
 static const struct got_error *
 histedit_edit_script(struct got_histedit_list *histedit_cmds,
     struct got_object_id_queue *commits, const char *branch_name,
-    struct got_repository *repo)
+    int edit_logmsg_only, struct got_repository *repo)
 {
 	const struct got_error *err;
 	FILE *f = NULL;
@@ -6032,23 +6039,27 @@ histedit_edit_script(struct got_histedit_list *histedi
 	if (err)
 		goto done;
 
-	err = histedit_write_commit_list(commits, f, repo);
+	err = histedit_write_commit_list(commits, f, edit_logmsg_only, repo);
 	if (err)
 		goto done;
 
-	if (fclose(f) != 0) {
-		err = got_error_from_errno("fclose");
-		goto done;
-	}
-	f = NULL;
-
-	err = histedit_run_editor(histedit_cmds, path, commits, repo);
-	if (err) {
-		if (err->code != GOT_ERR_HISTEDIT_SYNTAX &&
-		    err->code != GOT_ERR_HISTEDIT_CMD)
+	if (edit_logmsg_only) {
+		rewind(f);
+		err = histedit_parse_list(histedit_cmds, f, repo);
+	} else {
+		if (fclose(f) != 0) {
+			err = got_error_from_errno("fclose");
 			goto done;
-		err = histedit_edit_list_retry(histedit_cmds, err,
-		    commits, path, branch_name, repo);
+		}
+		f = NULL;
+		err = histedit_run_editor(histedit_cmds, path, commits, repo);
+		if (err) {
+			if (err->code != GOT_ERR_HISTEDIT_SYNTAX &&
+			    err->code != GOT_ERR_HISTEDIT_CMD)
+				goto done;
+			err = histedit_edit_list_retry(histedit_cmds, err,
+			    commits, path, branch_name, repo);
+		}
 	}
 done:
 	if (f && fclose(f) != 0 && err == NULL)
@@ -6163,7 +6174,7 @@ histedit_edit_list_retry(struct got_histedit_list *his
 		} else if (resp == 'r') {
 			histedit_free_list(histedit_cmds);
 			err = histedit_edit_script(histedit_cmds,
-			    commits, branch_name, repo);
+			    commits, branch_name, 0, repo);
 			if (err) {
 				if (err->code != GOT_ERR_HISTEDIT_SYNTAX &&
 				    err->code != GOT_ERR_HISTEDIT_CMD)
@@ -6354,6 +6365,7 @@ cmd_histedit(int argc, char *argv[])
 	struct got_commit_object *commit = NULL;
 	int ch, rebase_in_progress = 0, did_something;
 	int edit_in_progress = 0, abort_edit = 0, continue_edit = 0;
+	int edit_logmsg_only = 0;
 	const char *edit_script_path = NULL;
 	unsigned char rebase_status = GOT_STATUS_NO_CHANGE;
 	struct got_object_id_queue commits;
@@ -6367,7 +6379,7 @@ cmd_histedit(int argc, char *argv[])
 	TAILQ_INIT(&histedit_cmds);
 	TAILQ_INIT(&merged_paths);
 
-	while ((ch = getopt(argc, argv, "acF:")) != -1) {
+	while ((ch = getopt(argc, argv, "acF:m")) != -1) {
 		switch (ch) {
 		case 'a':
 			abort_edit = 1;
@@ -6378,6 +6390,9 @@ cmd_histedit(int argc, char *argv[])
 		case 'F':
 			edit_script_path = optarg;
 			break;
+		case 'm':
+			edit_logmsg_only = 1;
+			break;
 		default:
 			usage_histedit();
 			/* NOTREACHED */
@@ -6393,7 +6408,13 @@ cmd_histedit(int argc, char *argv[])
 		err(1, "pledge");
 #endif
 	if (abort_edit && continue_edit)
-		usage_histedit();
+		errx(1, "histedit's -a and -c options are mutually exclusive");
+	if (edit_script_path && edit_logmsg_only)
+		errx(1, "histedit's -F and -m options are mutually exclusive");
+	if (abort_edit && edit_logmsg_only)
+		errx(1, "histedit's -a and -m options are mutually exclusive");
+	if (continue_edit && edit_logmsg_only)
+		errx(1, "histedit's -c and -m options are mutually exclusive");
 	if (argc != 0)
 		usage_histedit();
 
@@ -6432,6 +6453,14 @@ cmd_histedit(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	if (edit_in_progress && edit_logmsg_only) {
+		error = got_error_msg(GOT_ERR_HISTEDIT_BUSY,
+		    "histedit operation is in progress in this "
+		    "work tree and must be continued or aborted "
+		    "before the -m option can be used");
+		goto done;
+	}
+
 	if (edit_in_progress && abort_edit) {
 		error = got_worktree_histedit_continue(&resume_commit_id,
 		    &tmp_branch, &branch, &base_commit_id, &fileindex,
@@ -6564,7 +6593,7 @@ cmd_histedit(int argc, char *argv[])
 			if (strncmp(branch_name, "refs/heads/", 11) == 0)
 				branch_name += 11;
 			error = histedit_edit_script(&histedit_cmds, &commits,
-			    branch_name, repo);
+			    branch_name, edit_logmsg_only, repo);
 			if (error) {
 				got_worktree_histedit_abort(worktree, fileindex,
 				    repo, branch, base_commit_id,