This is an archive of the discontinued LLVM Phabricator instance.

git-clang-format: format index not worktree when using --staged
ClosedPublic

Authored by Maetveis on Jul 19 2022, 11:59 AM.

Details

Summary

When --staged (or --cached) use the index for formatting as well, not just for the line numbers
to format.
Without this change git-clang-format gets the changed line numbers based on the index, but then
formats these lines on the working tree version of the file.
This is a problem when the working tree and index differ. One common case would be
(and is the motivation behind this patch) when applying the suggested changes git-clang-format --staged,
then forgetting to add the applied changes. When git-clang-format --staged --diff is used in a
pre-commit hook in this scenario, then the hook would allow committing the improperly formatted changes,
as the file is correctly formatted in the work tree.

Fixes https://github.com/llvm/llvm-project/issues/56797.

Diff Detail

Event Timeline

Maetveis created this revision.Jul 19 2022, 11:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 11:59 AM
Herald added a subscriber: arphaman. · View Herald Transcript
Maetveis requested review of this revision.Jul 19 2022, 11:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 11:59 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
Maetveis updated this revision to Diff 448563.Jul 29 2022, 2:57 AM

Updated to add missing comma after 'git ls-tree'. It broke normal (non staged) operation.

Friendly Ping.

So trying to understand the problem statement, is it:

  1. you have some files staged
  2. and then you have to change them locally (review comment)
  3. but forget to git add them,
  4. you run git clang-format --staged
  5. and it formats the new file (not added) based on the line numbers that are changing in the already staged file, which could be a different range to the original (is that correct?)
  6. You think you've formatted the new file correctly (but likely missed a line or two)
  7. You perform git add (as you now notice you've missed adding it)
  8. You commit, but a commit hook tells you that you didn't clang format. (or worse still you are able to commit and push but you are pushing a badly formatted file, potentially)

is that correct?

Maetveis added a comment.EditedAug 8 2022, 10:39 AM

So trying to understand the problem statement, is it:

  1. you have some files staged
  2. and then you have to change them locally (review comment)
  3. but forget to git add them,
  4. you run git clang-format --staged
  5. and it formats the new file (not added) based on the line numbers that are changing in the already staged file, which could be a different range to the original (is that correct?)
  6. You think you've formatted the new file correctly (but likely missed a line or two)
  7. You perform git add (as you now notice you've missed adding it)
  8. You commit, but a commit hook tells you that you didn't clang format. (or worse still you are able to commit and push but you are pushing a badly formatted file, potentially)

is that correct?

Not exactly, in 5 git-clang-format --staged would refuse to change anything, because the same file is modified in both the index and the worktree.
But with --diff, yes it would run clang-format on the new file, but with the line numbers based on the index, then show the diff with this result.

Also at 8 there would be no problem, as there's no two versions of the file anymore. The issue can only appear when there is a file that is different in the index and on disk (Not all changes to it are staged).

I think this captures the original case well:

  1. Have a commit hook script that uses git-clang-format --staged --diff to reject commits that would be badly formatted
  2. Change a file, add changes with incorrect formatting
  3. add the file to the index via git add
  4. Try to commit
  5. The commit hook rejects the commit, gives the diff that needs to be applied to fix
  6. Fix the formatting, but forget to git add
  7. Commit
  8. Commit succeeds, but it should have failed, the resulting commit has incorrect formatting (because it does not include the formatting changes)
owenpan added inline comments.Aug 9 2022, 12:17 PM
clang/tools/clang-format/git-clang-format
182–194

To refactor the code a little.

400–401

Nit: keep two empty lines between top-level functions and break the long comment.

406

To break the long line.

418–419

To keep lines within the 80-column limit.

435

To break the long line.

Maetveis updated this revision to Diff 451257.Aug 9 2022, 1:34 PM

Address formatting and stylistic comments.

owenpan accepted this revision.Aug 9 2022, 4:09 PM

Please mark review comments as done if you have addressed them.

clang/tools/clang-format/git-clang-format
415

Nit: end the sentence with a period as previously suggested.

418–419

Nit: extraneous trailing whitespace and lack of a full stop.

This revision is now accepted and ready to land.Aug 9 2022, 4:09 PM
owenpan edited the summary of this revision. (Show Details)Aug 9 2022, 4:10 PM
Maetveis updated this revision to Diff 451584.Aug 10 2022, 11:32 AM
Maetveis marked 7 inline comments as done.

Sorry, I somehow missed the big obvious checkbox to mark the comments, fixed now.
I don't have commit access could you commit if the last change seems okay to you?

Name: Gergely Meszaros
Email: meszaros.gergely97@gmail.com