diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index a42b323..3f6b553 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -30,3 +30,11 @@ pass_filenames: false always_run: true minimum_pre_commit_version: '0.19.0' +- id: sbt-scalafmt-apply + name: scalafmt formatting fix + stages: [commit,push] + language: python + entry: scalafmt-apply + pass_filenames: false + always_run: true + minimum_pre_commit_version: '0.19.0' diff --git a/README.adoc b/README.adoc index d4ee16d..1ba97e3 100644 --- a/README.adoc +++ b/README.adoc @@ -26,6 +26,7 @@ Currently, they include the following: - `sbt-unused-imports` - as above, but also adds the "unused imports" warning. - `sbt-scalafmt` - runs `scalafmtCheckAll`. - `sbt-wartremover` - runs the wartremover plugin. +- `sbt-scalafmt-apply` - runs `scalafmtAll`, as sbt-scalafmt but also applies reformatting to changed files. To add one or more of the hooks into your repo: @@ -45,6 +46,7 @@ repos: - id: sbt-unused-imports #includes fatal warnings, arguments optional args: [--scope={defaultScope}] - id: sbt-scalafmt + - id: sbt-scalafmt-apply - id: sbt-wartremover #arguments are optional args: [--warts=Warts.unsafe, --scope={defaultScope}] ---- @@ -53,7 +55,7 @@ repos: [NOTE] -- -All hooks except for `sbt-scalafmt` have the optional `scope` argument, which allows to define what source scopes +All hooks except for `sbt-scalafmt` and `sbt-scalafmt-apply` have the optional `scope` argument, which allows to define what source scopes are relevant for the hook's check. The default is `{defaultScope}`. -- diff --git a/pre_commit_hooks/runner.py b/pre_commit_hooks/runner.py index 10993eb..850593b 100644 --- a/pre_commit_hooks/runner.py +++ b/pre_commit_hooks/runner.py @@ -12,3 +12,17 @@ def run_sbt_command(task_def, missing_plugin_check_string=None, missing_plugin_e print(raw_output) return sbt_process.returncode + +def run_git_add_modified(): + """Adds stages files if changes are detected.""" + try: + # Check if there are modified files before running git add -u + status = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True) + + if status.stdout.strip(): # If there are modified files + print("Staged formatted files.") + return subprocess.run(["git", "add", "-u"], check=True) + + except subprocess.CalledProcessError as e: + print(f"Error: {e}") + return e.returncode diff --git a/pre_commit_hooks/scalafmt_apply.py b/pre_commit_hooks/scalafmt_apply.py new file mode 100644 index 0000000..f7591d2 --- /dev/null +++ b/pre_commit_hooks/scalafmt_apply.py @@ -0,0 +1,19 @@ +from pre_commit_hooks.runner import run_sbt_command, run_git_add_modified +from colorama import init as colorama_init, Fore + +TASK_SCALAFMT = 'scalafmtAll' +MISSING_PLUGIN_CHECK_STRING = 'Not a valid key: scalafmtAll' +MISSING_PLUGIN_ERROR_MSG = f'{Fore.RED}ERROR: scalafmt SBT plugin not present! See {Fore.BLUE}https://scalameta.org/scalafmt/docs/installation.html#sbt{Fore.RED} for installation instructions.' + + +def main(argv=None): + colorama_init() + + sbt = run_sbt_command(f'; clean ; {TASK_SCALAFMT}', MISSING_PLUGIN_CHECK_STRING, MISSING_PLUGIN_ERROR_MSG) + run_git_add_modified() + + return sbt + + +if __name__ == '__main__': + exit(main()) diff --git a/setup.cfg b/setup.cfg index 9e198a3..7e99faf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,3 +13,4 @@ console_scripts = sbt-wartremover = pre_commit_hooks.sbt_wartremover:main scalafmt = pre_commit_hooks.scalafmt:main sbt-fatal-warnings = pre_commit_hooks.sbt_fatal_warnings:main + scalafmt-apply = pre_commit_hooks.scalafmt_apply:main