commit - 96d694ac3bc159099a9ad93aa49ec7ac1764b18d
commit + 75a8c854e063f97e5a2605f5256a1ce15ffb2f24
blob - 518e73d32dd54163f0c184e0373f963ae473079b
blob + 6909ba95d7617d65c7fcad655d3baa1f1543340a
--- got/got.1
+++ got/got.1
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 ,
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
}
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;
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) {
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);