aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtools/clang-format.py33
-rwxr-xr-xtools/clang-format_unittest.py16
2 files changed, 40 insertions, 9 deletions
diff --git a/tools/clang-format.py b/tools/clang-format.py
index 24ef711..1d5f1ac 100755
--- a/tools/clang-format.py
+++ b/tools/clang-format.py
@@ -26,7 +26,7 @@ del _path
# We have to import our local modules after the sys.path tweak. We can't use
# relative imports because this is an executable program, not a module.
-# pylint: disable=wrong-import-position
+# pylint: disable=wrong-import-position,import-error
import rh.shell
import rh.utils
@@ -82,15 +82,32 @@ def main(argv):
result = rh.utils.run(cmd, capture_output=True, check=False)
# Newer versions of git-clang-format will exit 1 when it worked. Assume a
# real failure is any exit code above 1, or any time stderr is used, or if
- # it exited 1 but didn't produce anything useful to stdout. If it exited 0,
+ # it exited 1 and produce useful format diffs to stdout. If it exited 0,
# then assume all is well and we'll attempt to parse its output below.
+ ret_code = None
if (result.returncode > 1 or result.stderr or
- (not result.stdout and result.returncode)):
- print(f'clang-format failed:\ncmd: {result.cmdstr}\n'
- f'stdout:\n{result.stdout}\nstderr:\n{result.stderr}',
- file=sys.stderr)
- print('\nPlease report this to the clang team.', file=sys.stderr)
- return 1
+ (result.stdout and result.returncode)):
+ # Apply fix if the flag is set and clang-format shows it is fixible.
+ if opts.fix and result.stdout and result.returncode:
+ result = rh.utils.run(['git', 'apply'], input=result.stdout,
+ check=False)
+ ret_code = result.returncode
+ if ret_code:
+ print('Error: Unable to automatically fix things.\n'
+ ' Make sure your checkout is clean first.\n'
+ ' If you have multiple commits, you might have to '
+ 'manually rebase your tree first.',
+ file=sys.stderr)
+
+ else: # Regular clang-format aborts/fails.
+ print(f'clang-format failed:\ncmd: {result.cmdstr}\n'
+ f'stdout:\n{result.stdout}\n', file=sys.stderr)
+ if result.returncode > 1 or result.stderr:
+ print('\nPlease report this to the clang team.\n',
+ f'stderr:\n{result.stderr}', file=sys.stderr)
+ ret_code = 1
+
+ return ret_code
stdout = result.stdout
if stdout.rstrip('\n') == 'no modified files to format':
diff --git a/tools/clang-format_unittest.py b/tools/clang-format_unittest.py
index 1128f65..8dfb5cf 100755
--- a/tools/clang-format_unittest.py
+++ b/tools/clang-format_unittest.py
@@ -27,7 +27,7 @@ sys.path.insert(0, str(DIR.parent))
# We have to import our local modules after the sys.path tweak. We can't use
# relative imports because this is an executable program, not a module.
-# pylint: disable=wrong-import-position
+# pylint: disable=wrong-import-position,import-error
import rh.utils
@@ -71,6 +71,12 @@ class GitClangFormatExit(unittest.TestCase):
def test_diff_exit_1_no_output(self):
"""Test exit 1 w/no output."""
with git_clang_format('exit 1') as script:
+ result = run_clang_format(script, ['--working-tree'])
+ self.assertEqual(result.stdout, '')
+
+ def test_diff_exit_1_output(self):
+ """Test exit 1 with output."""
+ with git_clang_format('echo bad; exit 1') as script:
with self.assertRaises(rh.utils.CalledProcessError) as e:
run_clang_format(script, ['--working-tree'])
self.assertIn('clang-format failed', e.exception.stderr)
@@ -89,6 +95,14 @@ class GitClangFormatExit(unittest.TestCase):
run_clang_format(script, ['--working-tree'])
self.assertIn('clang-format failed', e.exception.stderr)
+ def test_fix_exit_1_output(self):
+ """Test fix with incorrect patch syntax."""
+ with git_clang_format('echo bad patch; exit 1') as script:
+ with self.assertRaises(rh.utils.CalledProcessError) as e:
+ run_clang_format(script, ['--working-tree', '--fix'])
+ self.assertIn('Error: Unable to automatically fix things',
+ e.exception.stderr)
+
if __name__ == '__main__':
unittest.main()