Add empty file handling in JujutsuPatcher.

Review Request #14760 — Created Jan. 6, 2026 and updated

Information

RBTools
master

Reviewers

In my previous change that updated the patching infrastructure to add
support for patching binary files, I changed the top-level Patcher class
so it would (when supported) call apply_patch_for_empty_files. This
caused a regression with Jujutsu, where we had no implementation of
that. I didn't catch this because it was hidden behind a conditional
which was false in the case of unit tests, since we weren't
instantiating the client with a capabilities object.

This change adds an implementation of that method for Jujutsu which
works similar to the SVN and Perforce implementations. Mercurial and Git
are otherwise immune because they use SCM-native patching which handles
empty files itself (hg import and git apply, respectively).

Some of the jj unit tests were incorrectly named, saying they included
empty files when they didn't. I've fixed those up, deleted a test which
did not do anything unique, and added two new tests similar to ones we
have in GitPatcherTests for ensuring that empty files work correctly.

To be complete, I've also added the default capabilities object to the
Git, Mercurial, and Perforce tests, just to ensure that the result of
supports_empty_files() will be correct when running the tests.

Ran unit tests.

Summary ID
Add empty file handling in JujutsuPatcher.
In my previous change that updated the patching infrastructure to add support for patching binary files, I changed the top-level Patcher class so it would (when supported) call `apply_patch_for_empty_files`. This caused a regression with Jujutsu, where we had no implementation of that. I didn't catch this because it was hidden behind a conditional which was false in the case of unit tests, since we weren't instantiating the client with a capabilities object. This change adds an implementation of that method for Jujutsu which works similar to the SVN and Perforce implementations. Mercurial and Git are otherwise immune because they use SCM-native patching which handles empty files itself (`hg import` and `git apply`, respectively). Some of the jj unit tests were incorrectly named, saying they included empty files when they didn't. I've fixed those up, deleted a test which did not do anything unique, and added two new tests similar to ones we have in `GitPatcherTests` for ensuring that empty files work correctly. To be complete, I've also added the default capabilities object to the Git, Mercurial, and Perforce tests, just to ensure that the result of `supports_empty_files()` will be correct when running the tests. Testing Done: Ran unit tests.
zyloxzouusozptwmwyrvtswmorwxovus
Description From Last Updated

continuation line over-indented for visual indent Column: 64 Error code: E127

reviewbotreviewbot

blank line at end of file Column: 1 Error code: W391

reviewbotreviewbot

This should say "deleted empty files"

chipx86chipx86

What raises this?

chipx86chipx86

Blank line between these.

chipx86chipx86

We're decoding multiple times, which is a bit wasteful. We should decode in a separate step, or an internal comprehension: …

chipx86chipx86

Blank line here.

chipx86chipx86

Blank line here.

chipx86chipx86

This log should probably include the filename in quotes followed by the error message.

chipx86chipx86

No trailing period here.

chipx86chipx86

Blank line between statements and blocks.

chipx86chipx86

We don't normally do an explicit mode=, just leaving it as positional. Here and below.

chipx86chipx86

The second keyword argument should be on its own line.

chipx86chipx86

No trailing period here.

chipx86chipx86

Blank line between statements and blocks.

chipx86chipx86

Same comment re: one keyword argument per line.

chipx86chipx86

Blank line here.

chipx86chipx86

Is there a chance that one file deletion fails, but the others succeed? In that case we'd return True from …

maubinmaubin
Checks run (1 failed, 1 succeeded)
flake8 failed.
JSHint passed.

flake8

david
chipx86
  1. 
      
  2. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
    Show all issues

    This should say "deleted empty files"

  3. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
     
    Show all issues

    What raises this?

    1. Copy/paste from the parent class docstring.

  4. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line between these.

  5. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
     
     
     
     
     
     
     
     
    Show all issues

    We're decoding multiple times, which is a bit wasteful. We should decode in a separate step, or an internal comprehension:

    added_files = [
        filename
        for filename in (
            filename.decode('utf-8')
            for filename in added_files_re.findall(patch_content)
        )
        if filename not in binary_file_paths
    ]
    
  6. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line here.

  7. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line here.

  8. rbtools/clients/jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    This log should probably include the filename in quotes followed by the error message.

  9. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
    Show all issues

    No trailing period here.

  10. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line between statements and blocks.

  11. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
    Show all issues

    We don't normally do an explicit mode=, just leaving it as positional. Here and below.

    1. When adding the encoding argument, I've been turning mode into a kwarg for clarity. I think it reads much better than just a stringly-typed positional arg.

  12. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    The second keyword argument should be on its own line.

  13. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
    Show all issues

    No trailing period here.

  14. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line between statements and blocks.

  15. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Same comment re: one keyword argument per line.

  16. rbtools/clients/tests/test_jujutsu.py (Diff revision 2)
     
     
     
    Show all issues

    Blank line here.

  17. 
      
david
Review request changed
Commits:
Summary ID
Add empty file handling in JujutsuPatcher.
In my previous change that updated the patching infrastructure to add support for patching binary files, I changed the top-level Patcher class so it would (when supported) call `apply_patch_for_empty_files`. This caused a regression with Jujutsu, where we had no implementation of that. I didn't catch this because it was hidden behind a conditional which was false in the case of unit tests, since we weren't instantiating the client with a capabilities object. This change adds an implementation of that method for Jujutsu which works similar to the SVN and Perforce implementations. Mercurial and Git are otherwise immune because they use SCM-native patching which handles empty files itself (`hg import` and `git apply`, respectively). Some of the jj unit tests were incorrectly named, saying they included empty files when they didn't. I've fixed those up, deleted a test which did not do anything unique, and added two new tests similar to ones we have in `GitPatcherTests` for ensuring that empty files work correctly. To be complete, I've also added the default capabilities object to the Git, Mercurial, and Perforce tests, just to ensure that the result of `supports_empty_files()` will be correct when running the tests. Testing Done: Ran unit tests.
zyloxzouusozptwmwyrvtswmorwxovus
Add empty file handling in JujutsuPatcher.
In my previous change that updated the patching infrastructure to add support for patching binary files, I changed the top-level Patcher class so it would (when supported) call `apply_patch_for_empty_files`. This caused a regression with Jujutsu, where we had no implementation of that. I didn't catch this because it was hidden behind a conditional which was false in the case of unit tests, since we weren't instantiating the client with a capabilities object. This change adds an implementation of that method for Jujutsu which works similar to the SVN and Perforce implementations. Mercurial and Git are otherwise immune because they use SCM-native patching which handles empty files itself (`hg import` and `git apply`, respectively). Some of the jj unit tests were incorrectly named, saying they included empty files when they didn't. I've fixed those up, deleted a test which did not do anything unique, and added two new tests similar to ones we have in `GitPatcherTests` for ensuring that empty files work correctly. To be complete, I've also added the default capabilities object to the Git, Mercurial, and Perforce tests, just to ensure that the result of `supports_empty_files()` will be correct when running the tests. Testing Done: Ran unit tests.
zyloxzouusozptwmwyrvtswmorwxovus

Checks run (2 succeeded)

flake8 passed.
JSHint passed.
maubin
  1. 
      
  2. rbtools/clients/jujutsu.py (Diff revision 3)
     
     
     
     
     
     
     
     
     
    Show all issues

    Is there a chance that one file deletion fails, but the others succeed? In that case we'd return True from this. Is that what we want? Or do we want to return False if at least one file fails.

  3.