diff mbox series

[b4] ez: Prevent overwriting an unrelated cover letter

Message ID 20240328-avoid-overwritting-cover-letter-v1-1-161d30ee533c@bootlin.com (mailing list archive)
State New
Headers show
Series [b4] ez: Prevent overwriting an unrelated cover letter | expand

Commit Message

Louis Chauvet March 28, 2024, 9:25 a.m. UTC
When editing a cover-letter, b4 expectedly selects as base the
cover-letter of the currently checked-out Git branch. When
saving/closing the editor, b4 also saves the changes as the
new cover-letter for the currently checked-out Git branch.

While simplistic and apparently totally fine, it does not play well
when working on multiple branches. Said otherwise, the following
sequence of events will write the wrong file, possibly smashing a
valuable cover-letter:

	$ b4 prep --edit-cover
	<make some changes>
	$ git checkout another-branch
	<oh, I forgot to save and close the cover letter editor!>
	*crunch*

Add a simple check to only overwrite the cover-letter if it corresponds
to the one that was originally opened, otherwise warn the user and save
it in a temporary spot.

Cc: tools@kernel.org
Cc: miquel.raynal@bootlin.com
Cc: thomas.petazzoni@bootlin.com

Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 src/b4/ez.py | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)


---
base-commit: 23970c613f40356cc88716d07c2d427ca024e489
change-id: 20240328-avoid-overwritting-cover-letter-554bcd29b240

Best regards,

Comments

Konstantin Ryabitsev March 28, 2024, 2:19 p.m. UTC | #1
On Thu, Mar 28, 2024 at 10:25:43AM +0100, Louis Chauvet wrote:
> When editing a cover-letter, b4 expectedly selects as base the
> cover-letter of the currently checked-out Git branch. When
> saving/closing the editor, b4 also saves the changes as the
> new cover-letter for the currently checked-out Git branch.
> 
> While simplistic and apparently totally fine, it does not play well
> when working on multiple branches. Said otherwise, the following
> sequence of events will write the wrong file, possibly smashing a
> valuable cover-letter:

Makes sense, good catch!

>  def edit_cover() -> None:
> +    # To avoid losing the cover letter, ensure that we are still on the same branch as when the cover-letter was originally opened.
> +    read_branch = b4.git_get_current_branch()
>      cover, tracking = load_cover()
>      bcover = cover.encode()
>      new_bcover = b4.edit_in_editor(bcover, filehint='COMMIT_EDITMSG')

I suggest we implement this check in b4.edit_in_editor(), so it applies to all
situations, not just for cover editing:

- get and remember the current branch name
- open file in editor
- re-check the current branch name
- save the contents as temporary file
- complain via logger.critical
- throw RuntimeError

Does that make sense?

> @@ -768,8 +772,15 @@ def edit_cover() -> None:
>      if not len(new_cover):
>          logger.info('New cover letter blank, leaving current one unchanged.')
>          return
> -
> -    store_cover(new_cover, tracking)
> +    write_branch = b4.git_get_current_branch()
> +    if write_branch != read_branch:
> +        with NamedTemporaryFile(mode="w", prefix=f"cover-{read_branch}".replace("/", "-"), delete=False) as save_file:
> +            save_file.write(new_cover)
> +            logger.critical(f'The cover letter was read on the branch {read_branch} but the current branch is now {write_branch}.')
> +            logger.critical(f'To avoid overwriting an unrelated cover letter, the operation is canceled and your new '
> +                            f'cover letter stored at {save_file.name}')

Best practice is to use %s expansion for logger calls, because this way the
substitution doesn't even happen if we're in a logging level above the one
specified.

Thanks!

-K
diff mbox series

Patch

diff --git a/src/b4/ez.py b/src/b4/ez.py
index 1d360410d771..c322953564a0 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -8,6 +8,8 @@  __author__ = 'Konstantin Ryabitsev <konstantin@linuxfoundation.org>'
 import email.message
 import os
 import sys
+from tempfile import NamedTemporaryFile
+
 import b4
 import re
 import argparse
@@ -758,6 +760,8 @@  class FRCommitMessageEditor:
 
 
 def edit_cover() -> None:
+    # To avoid losing the cover letter, ensure that we are still on the same branch as when the cover-letter was originally opened.
+    read_branch = b4.git_get_current_branch()
     cover, tracking = load_cover()
     bcover = cover.encode()
     new_bcover = b4.edit_in_editor(bcover, filehint='COMMIT_EDITMSG')
@@ -768,8 +772,15 @@  def edit_cover() -> None:
     if not len(new_cover):
         logger.info('New cover letter blank, leaving current one unchanged.')
         return
-
-    store_cover(new_cover, tracking)
+    write_branch = b4.git_get_current_branch()
+    if write_branch != read_branch:
+        with NamedTemporaryFile(mode="w", prefix=f"cover-{read_branch}".replace("/", "-"), delete=False) as save_file:
+            save_file.write(new_cover)
+            logger.critical(f'The cover letter was read on the branch {read_branch} but the current branch is now {write_branch}.')
+            logger.critical(f'To avoid overwriting an unrelated cover letter, the operation is canceled and your new '
+                            f'cover letter stored at {save_file.name}')
+    else:
+        store_cover(new_cover, tracking)
     logger.info('Cover letter updated.')