Commit Diff


commit - 96d694ac3bc159099a9ad93aa49ec7ac1764b18d
commit + 75a8c854e063f97e5a2605f5256a1ce15ffb2f24
blob - 518e73d32dd54163f0c184e0373f963ae473079b
blob + 6909ba95d7617d65c7fcad655d3baa1f1543340a
--- got/got.1
+++ got/got.1
@@ -2038,8 +2038,13 @@ When a file changed by
 is committed with
 .Cm got commit ,
 the log messages of relevant merged commits will then appear in the editor,
-where the messages must be further adjusted to convey the reasons for
+where the messages should be further adjusted to convey the reasons for
 cherrypicking the changes.
+At the very least, comment lines must be removed.
+Otherwise
+.Cm got commit
+will fail with an unmodified log message error.
+.Pp
 If all the changes in all files touched by a given commit are discarded,
 e.g. with
 .Cm got revert ,
@@ -2141,8 +2146,13 @@ When a file changed by
 is committed with
 .Cm got commit ,
 the log messages of relevant reverse-merged commits will then appear in
-the editor, where the messages must be further adjusted to convey the
+the editor, where the messages should be further adjusted to convey the
 reasons for backing out the changes.
+At the very least, comment lines must be removed.
+Otherwise
+.Cm got commit
+will fail with an unmodified log message error.
+.Pp
 If all the changes in all files touched by a given commit are discarded,
 e.g. with
 .Cm got revert ,
blob - 6e5b65aa69900bbf246ac029c6cd4c455abe1b84
blob + bee0d18c081539ca419adef37c4d86b0cb38d282
--- got/got.c
+++ got/got.c
@@ -389,13 +389,60 @@ doneediting:
 }
 
 static const struct got_error *
+read_logmsg(char **logmsg, size_t *len, FILE *fp, size_t filesize,
+    int strip_comments)
+{
+	const struct got_error *err = NULL;
+	char *line = NULL;
+	size_t linesize = 0;
+
+	*logmsg = NULL;
+	*len = 0;
+
+	if (fseeko(fp, 0L, SEEK_SET) == -1)
+		return got_error_from_errno("fseeko");
+
+	*logmsg = malloc(filesize + 1);
+	if (*logmsg == NULL)
+		return got_error_from_errno("malloc");
+	(*logmsg)[0] = '\0';
+
+	while (getline(&line, &linesize, fp) != -1) {
+		if ((strip_comments && line[0] == '#') ||
+		    (*len == 0 && line[0] == '\n'))
+			continue; /* remove comments and leading empty lines */
+		*len = strlcat(*logmsg, line, filesize + 1);
+		if (*len >= filesize + 1) {
+			err = got_error(GOT_ERR_NO_SPACE);
+			goto done;
+		}
+	}
+	if (ferror(fp)) {
+		err = got_ferror(fp, GOT_ERR_IO);
+		goto done;
+	}
+
+	while (*len > 0 && (*logmsg)[*len - 1] == '\n') {
+		(*logmsg)[*len - 1] = '\0';
+		(*len)--;
+	}
+done:
+	free(line);
+	if (err) {
+		free(*logmsg);
+		*logmsg = NULL;
+		*len = 0;
+	}
+	return err;
+}
+
+static const struct got_error *
 edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
     const char *initial_content, size_t initial_content_len,
     int require_modification)
 {
 	const struct got_error *err = NULL;
 	char *line = NULL;
-	size_t linesize = 0;
 	struct stat st, st2;
 	FILE *fp = NULL;
 	size_t len, logmsg_len;
@@ -435,8 +482,8 @@ edit_logmsg(char **logmsg, const char *editor, const c
 	s = buf;
 	len = 0;
 	while ((line = strsep(&s, "\n")) != NULL) {
-		if ((line[0] == '#' || (len == 0 && line[0] == '\n')))
-			continue; /* remove comments and leading empty lines */
+		if (len == 0 && line[0] == '\n')
+			continue; /* remove leading empty lines */
 		len = strlcat(initial_content_stripped, line,
 		    initial_content_len + 1);
 		if (len >= initial_content_len + 1) {
@@ -449,47 +496,35 @@ edit_logmsg(char **logmsg, const char *editor, const c
 		len--;
 	}
 
-	logmsg_len = st2.st_size;
-	*logmsg = malloc(logmsg_len + 1);
-	if (*logmsg == NULL)
-		return got_error_from_errno("malloc");
-	(*logmsg)[0] = '\0';
-
 	fp = fopen(logmsg_path, "re");
 	if (fp == NULL) {
 		err = got_error_from_errno("fopen");
 		goto done;
 	}
 
-	len = 0;
-	while (getline(&line, &linesize, fp) != -1) {
-		if ((line[0] == '#' || (len == 0 && line[0] == '\n')))
-			continue; /* remove comments and leading empty lines */
-		len = strlcat(*logmsg, line, logmsg_len + 1);
-		if (len >= logmsg_len + 1) {
-			err = got_error(GOT_ERR_NO_SPACE);
-			goto done;
-		}
-	}
-	free(line);
-	if (ferror(fp)) {
-		err = got_ferror(fp, GOT_ERR_IO);
+	/*
+	 * Check whether the log message was modified.
+	 * Editing or removal of comments does count as a modifcation to
+	 * support reuse of existing log messages during cherrypick/backout.
+	 */
+	err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size, 0);
+	if (err)
 		goto done;
-	}
-	while (len > 0 && (*logmsg)[len - 1] == '\n') {
-		(*logmsg)[len - 1] = '\0';
-		len--;
-	}
+	if (require_modification &&
+	    strcmp(*logmsg, initial_content_stripped) == 0)
+		err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
+		    "no changes made to commit message, aborting");
 
-	if (len == 0) {
+	/* Read log message again, stripping comments this time around. */
+	free(*logmsg);
+	err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size, 1);
+	if (err)
+		goto done;
+	if (logmsg_len == 0) {
 		err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
 		    "commit message cannot be empty, aborting");
 		goto done;
 	}
-	if (require_modification &&
-	    strcmp(*logmsg, initial_content_stripped) == 0)
-		err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
-		    "no changes made to commit message, aborting");
 done:
 	free(initial_content_stripped);
 	free(buf);