From 56a4716cfbbfe00eb7a68364f29c480f98a15781 Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Mon, 11 Mar 2024 18:38:34 -0700 Subject: [PATCH] amend: respect git config commit.cleanup Git commit has several configuration options for how to strip comment lines out of the commit text. We generally want to support these because they affect whether we throw away prefixed lines that could be important text to the user. "strip" is just the default way we've been doing it, so refactor to also support "scissors" which has a different comment and removal method. "whitespace" and "verbatim" are simpler strategies that we can support as well, but get no additional comment Fixes: #148 --- revup/amend.py | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/revup/amend.py b/revup/amend.py index 40c5f73..e7a2fd4 100644 --- a/revup/amend.py +++ b/revup/amend.py @@ -16,8 +16,14 @@ RE_TOPIC_WITH_MODIFIERS = re.compile(r"(?P[a-zA-Z\-_0-9]+)(?P[\^~]+[0-9]*)?") +CLEANUP_SCISSOR_LINE = r"------------------------ >8 ------------------------" +CLEANUP_SCISSOR_COMMENT = """Do not modify or remove the line above. +Everything below it will be ignored.""" +CLEANUP_STRIP_COMMENT = """Please enter the commit message for your changes. Lines starting +with '#' will be ignored, and an empty message aborts the amend.""" -def invoke_editor_for_commit_msg( + +async def invoke_editor_for_commit_msg( git_ctx: git.Git, editor: str, topic_summary: str, commit_msg: str, cache_stat: str, stat: str ) -> str: """ @@ -32,19 +38,42 @@ def invoke_editor_for_commit_msg( full_stat.append(f"Original commit:\n{stat}") stat_text = "\n\n".join(full_stat) - comment_text = f"""\nPlease enter the commit message for your changes. Lines starting -with '#' will be ignored, and an empty message aborts the commit.\n{topic_summary}\n{stat_text}""" - comment_text = "\n# ".join(comment_text.splitlines()) + # Respect the configured option for commit msg cleanup. + cleanup_ret, cleanup_type = await git_ctx.git("config", "commit.cleanup", raiseonerror=False) + if cleanup_ret != 0: + # git's default if the message is being edited (which if we've reached this it is) + cleanup_type = "strip" + + comments = f"{topic_summary}\n{stat_text}" + if cleanup_type == "scissors": + comments = f"\n{CLEANUP_SCISSOR_LINE}\n{CLEANUP_SCISSOR_COMMENT}\n{comments}" + elif cleanup_type == "strip": + comments = f"\n{CLEANUP_STRIP_COMMENT}\n{comments}" + + comments = "\n# ".join(comments.splitlines()) with open(git_ctx.get_scratch_dir() + "/COMMIT_EDITMSG", mode="w") as temp_file: - temp_file.write(f"{commit_msg}\n{comment_text}") + temp_file.write(f"{commit_msg}\n{comments}") subprocess.check_call((*shlex.split(editor), temp_file.name)) with open(temp_file.name, "r") as editor_file: msg = editor_file.read() - # Strip out comment lines - return re.sub(r"^\s*#.*$", "", msg, flags=re.M).strip() + if cleanup_type == "strip": + # Strip out comment lines + msg = re.sub(r"^#.*$\n", "", msg, flags=re.M) + elif cleanup_type == "scissors": + msg = msg.split("# " + CLEANUP_SCISSOR_LINE)[0] + + if cleanup_type != "verbatim": + # Match behavior of git, which will trim all trailing whitespace + msg = re.sub(r"[ \t]+$", "", msg, flags=re.M) + # collapse consecutive empty lines + msg = re.sub(r"[\n]{3,}", "\n\n", msg) + # and remove all leading and trailing whitespace and newlines + msg = msg.strip() + + return msg async def get_topic_summary(topics: topic_stack.TopicStack) -> str: @@ -165,7 +194,7 @@ async def get_has_unstaged() -> bool: stack[0].commit_msg = "" if args.edit and not args.drop: - new_msg = invoke_editor_for_commit_msg( + new_msg = await invoke_editor_for_commit_msg( git_ctx, git_ctx.editor, await get_topic_summary(topics) if args.parse_topics else "",