From 86efa907288199acf7bb11ea3f426b18b230a4bd Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Wed, 1 Jan 2020 22:54:34 -0500 Subject: Make hooked and dev-suite git hooks cross platform Up to this point hooked had been only designed to work on Windows, not because dev-suite didn't want to support it, but because doing so was an immense amount of work with no clear design due to how Unix and Window paths are not at all the same. While shebang notation works on them for both the paths are different. In order to get around this we wrap Ruby, Python, and Bash scripts on Windows with a different script that invokes the 'Git for Windows' sh.exe to run the actual interpreters on the script. These can work fine then as long as one has installed Git for Windows on their machine, and has a copy of py.exe or ruby.exe on their path to be invoked. There is one caveat. We have to assume that a user has installed their copy of Git for Windows in the default location. This means if they haven't the scripts will fail to run. There's not much we can do about this and it's just a necessary wart to provide cross platform capabilities for a project. All projects can be initialized now with one of the language choices and then have the proper files linked on their OS as part of the initialization. Those who need to just link them in an already existing project can just run `hooked link` in order to set their computer up. This again handles the differences between the platforms. This project is also updated to the new format of hooked so that collaboration is now not limited to just Unix based OSes. --- .dev-suite/hooked/applypatch-msg | 1 - .dev-suite/hooked/applypatch-msg.py | 1 + .dev-suite/hooked/commit-msg | 4 - .dev-suite/hooked/commit-msg.py | 1 + .dev-suite/hooked/post-applypatch | 1 - .dev-suite/hooked/post-applypatch.py | 1 + .dev-suite/hooked/post-checkout | 1 - .dev-suite/hooked/post-checkout.py | 1 + .dev-suite/hooked/post-commit | 1 - .dev-suite/hooked/post-commit.py | 1 + .dev-suite/hooked/post-merge | 1 - .dev-suite/hooked/post-merge.py | 1 + .dev-suite/hooked/post-receive | 2 - .dev-suite/hooked/post-receive.py | 1 + .dev-suite/hooked/post-rewrite | 1 - .dev-suite/hooked/post-rewrite.py | 1 + .dev-suite/hooked/post-update | 1 - .dev-suite/hooked/post-update.py | 1 + .dev-suite/hooked/pre-auto-gc | 1 - .dev-suite/hooked/pre-auto-gc.py | 1 + .dev-suite/hooked/pre-commit | 7 - .dev-suite/hooked/pre-commit.py | 7 + .dev-suite/hooked/pre-push | 1 - .dev-suite/hooked/pre-push.py | 1 + .dev-suite/hooked/pre-rebase | 1 - .dev-suite/hooked/pre-rebase.py | 1 + .dev-suite/hooked/pre-receive | 1 - .dev-suite/hooked/pre-receive.py | 1 + .dev-suite/hooked/prepare-commit-msg | 1 - .dev-suite/hooked/prepare-commit-msg.py | 1 + .dev-suite/hooked/push-to-checkout | 1 - .dev-suite/hooked/push-to-checkout.py | 1 + .dev-suite/hooked/sendemail-validate | 1 - .dev-suite/hooked/sendemail-validate.py | 1 + .dev-suite/hooked/update | 1 - .dev-suite/hooked/update.py | 1 + .dev-suite/hooked/wrapper/applypatch-msg.sh | 2 + .dev-suite/hooked/wrapper/commit-msg.sh | 2 + .dev-suite/hooked/wrapper/post-applypatch.sh | 2 + .dev-suite/hooked/wrapper/post-checkout.sh | 2 + .dev-suite/hooked/wrapper/post-commit.sh | 2 + .dev-suite/hooked/wrapper/post-merge.sh | 2 + .dev-suite/hooked/wrapper/post-receive.sh | 2 + .dev-suite/hooked/wrapper/post-rewrite.sh | 2 + .dev-suite/hooked/wrapper/post-update.sh | 2 + .dev-suite/hooked/wrapper/pre-auto-gc.sh | 2 + .dev-suite/hooked/wrapper/pre-commit.sh | 2 + .dev-suite/hooked/wrapper/pre-push.sh | 2 + .dev-suite/hooked/wrapper/pre-rebase.sh | 2 + .dev-suite/hooked/wrapper/pre-receive.sh | 2 + .dev-suite/hooked/wrapper/prepare-commit-msg.sh | 2 + .dev-suite/hooked/wrapper/push-to-checkout.sh | 2 + .dev-suite/hooked/wrapper/sendemail-validate.sh | 2 + .dev-suite/hooked/wrapper/update.sh | 2 + hooked/src/main.rs | 181 ++++++++++++++++++++---- hooked/tests/init.rs | 66 +++++++-- 56 files changed, 271 insertions(+), 64 deletions(-) delete mode 100755 .dev-suite/hooked/applypatch-msg create mode 100755 .dev-suite/hooked/applypatch-msg.py delete mode 100755 .dev-suite/hooked/commit-msg create mode 100755 .dev-suite/hooked/commit-msg.py delete mode 100755 .dev-suite/hooked/post-applypatch create mode 100755 .dev-suite/hooked/post-applypatch.py delete mode 100755 .dev-suite/hooked/post-checkout create mode 100755 .dev-suite/hooked/post-checkout.py delete mode 100755 .dev-suite/hooked/post-commit create mode 100755 .dev-suite/hooked/post-commit.py delete mode 100755 .dev-suite/hooked/post-merge create mode 100755 .dev-suite/hooked/post-merge.py delete mode 100755 .dev-suite/hooked/post-receive create mode 100755 .dev-suite/hooked/post-receive.py delete mode 100755 .dev-suite/hooked/post-rewrite create mode 100755 .dev-suite/hooked/post-rewrite.py delete mode 100755 .dev-suite/hooked/post-update create mode 100755 .dev-suite/hooked/post-update.py delete mode 100755 .dev-suite/hooked/pre-auto-gc create mode 100755 .dev-suite/hooked/pre-auto-gc.py delete mode 100755 .dev-suite/hooked/pre-commit create mode 100755 .dev-suite/hooked/pre-commit.py delete mode 100755 .dev-suite/hooked/pre-push create mode 100755 .dev-suite/hooked/pre-push.py delete mode 100755 .dev-suite/hooked/pre-rebase create mode 100755 .dev-suite/hooked/pre-rebase.py delete mode 100755 .dev-suite/hooked/pre-receive create mode 100755 .dev-suite/hooked/pre-receive.py delete mode 100755 .dev-suite/hooked/prepare-commit-msg create mode 100755 .dev-suite/hooked/prepare-commit-msg.py delete mode 100755 .dev-suite/hooked/push-to-checkout create mode 100755 .dev-suite/hooked/push-to-checkout.py delete mode 100755 .dev-suite/hooked/sendemail-validate create mode 100755 .dev-suite/hooked/sendemail-validate.py delete mode 100755 .dev-suite/hooked/update create mode 100755 .dev-suite/hooked/update.py create mode 100755 .dev-suite/hooked/wrapper/applypatch-msg.sh create mode 100755 .dev-suite/hooked/wrapper/commit-msg.sh create mode 100755 .dev-suite/hooked/wrapper/post-applypatch.sh create mode 100755 .dev-suite/hooked/wrapper/post-checkout.sh create mode 100755 .dev-suite/hooked/wrapper/post-commit.sh create mode 100755 .dev-suite/hooked/wrapper/post-merge.sh create mode 100755 .dev-suite/hooked/wrapper/post-receive.sh create mode 100755 .dev-suite/hooked/wrapper/post-rewrite.sh create mode 100755 .dev-suite/hooked/wrapper/post-update.sh create mode 100755 .dev-suite/hooked/wrapper/pre-auto-gc.sh create mode 100755 .dev-suite/hooked/wrapper/pre-commit.sh create mode 100755 .dev-suite/hooked/wrapper/pre-push.sh create mode 100755 .dev-suite/hooked/wrapper/pre-rebase.sh create mode 100755 .dev-suite/hooked/wrapper/pre-receive.sh create mode 100755 .dev-suite/hooked/wrapper/prepare-commit-msg.sh create mode 100755 .dev-suite/hooked/wrapper/push-to-checkout.sh create mode 100755 .dev-suite/hooked/wrapper/sendemail-validate.sh create mode 100755 .dev-suite/hooked/wrapper/update.sh diff --git a/.dev-suite/hooked/applypatch-msg b/.dev-suite/hooked/applypatch-msg deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/applypatch-msg +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/applypatch-msg.py b/.dev-suite/hooked/applypatch-msg.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/applypatch-msg.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/commit-msg b/.dev-suite/hooked/commit-msg deleted file mode 100755 index cc072bf..0000000 --- a/.dev-suite/hooked/commit-msg +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/bash - -# Check that the commit message is up to spec -hooked-commit-msg $@ diff --git a/.dev-suite/hooked/commit-msg.py b/.dev-suite/hooked/commit-msg.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/commit-msg.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-applypatch b/.dev-suite/hooked/post-applypatch deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-applypatch +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-applypatch.py b/.dev-suite/hooked/post-applypatch.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-applypatch.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-checkout b/.dev-suite/hooked/post-checkout deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-checkout +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-checkout.py b/.dev-suite/hooked/post-checkout.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-checkout.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-commit b/.dev-suite/hooked/post-commit deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-commit +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-commit.py b/.dev-suite/hooked/post-commit.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-commit.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-merge b/.dev-suite/hooked/post-merge deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-merge +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-merge.py b/.dev-suite/hooked/post-merge.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-merge.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-receive b/.dev-suite/hooked/post-receive deleted file mode 100755 index fb6b709..0000000 --- a/.dev-suite/hooked/post-receive +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/bash -git push github --all --force diff --git a/.dev-suite/hooked/post-receive.py b/.dev-suite/hooked/post-receive.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-receive.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-rewrite b/.dev-suite/hooked/post-rewrite deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-rewrite +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-rewrite.py b/.dev-suite/hooked/post-rewrite.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-rewrite.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/post-update b/.dev-suite/hooked/post-update deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/post-update +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/post-update.py b/.dev-suite/hooked/post-update.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/post-update.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/pre-auto-gc b/.dev-suite/hooked/pre-auto-gc deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/pre-auto-gc +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/pre-auto-gc.py b/.dev-suite/hooked/pre-auto-gc.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/pre-auto-gc.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/pre-commit b/.dev-suite/hooked/pre-commit deleted file mode 100755 index 4229848..0000000 --- a/.dev-suite/hooked/pre-commit +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash -set -eu -o pipefail - -cargo build --all -cargo test --all -rustup run nightly cargo fmt --all -- --check -cargo clippy --all --all-targets -- -W clippy::pedantic diff --git a/.dev-suite/hooked/pre-commit.py b/.dev-suite/hooked/pre-commit.py new file mode 100755 index 0000000..5ddbc42 --- /dev/null +++ b/.dev-suite/hooked/pre-commit.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +import subprocess + +subprocess.run("cargo build --all", shell=True, check=True) +subprocess.run("cargo test --all -- --test-threads=1", shell=True, check=True) +subprocess.run("rustup run nightly cargo fmt --all -- --check", shell=True, check=True) +subprocess.run("cargo clippy --all --all-targets -- -W clippy::pedantic", shell=True, check=True) diff --git a/.dev-suite/hooked/pre-push b/.dev-suite/hooked/pre-push deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/pre-push +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/pre-push.py b/.dev-suite/hooked/pre-push.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/pre-push.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/pre-rebase b/.dev-suite/hooked/pre-rebase deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/pre-rebase +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/pre-rebase.py b/.dev-suite/hooked/pre-rebase.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/pre-rebase.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/pre-receive b/.dev-suite/hooked/pre-receive deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/pre-receive +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/pre-receive.py b/.dev-suite/hooked/pre-receive.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/pre-receive.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/prepare-commit-msg b/.dev-suite/hooked/prepare-commit-msg deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/prepare-commit-msg +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/prepare-commit-msg.py b/.dev-suite/hooked/prepare-commit-msg.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/prepare-commit-msg.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/push-to-checkout b/.dev-suite/hooked/push-to-checkout deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/push-to-checkout +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/push-to-checkout.py b/.dev-suite/hooked/push-to-checkout.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/push-to-checkout.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/sendemail-validate b/.dev-suite/hooked/sendemail-validate deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/sendemail-validate +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/sendemail-validate.py b/.dev-suite/hooked/sendemail-validate.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/sendemail-validate.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/update b/.dev-suite/hooked/update deleted file mode 100755 index efcbaec..0000000 --- a/.dev-suite/hooked/update +++ /dev/null @@ -1 +0,0 @@ -#! /bin/bash \ No newline at end of file diff --git a/.dev-suite/hooked/update.py b/.dev-suite/hooked/update.py new file mode 100755 index 0000000..5f7ce86 --- /dev/null +++ b/.dev-suite/hooked/update.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 \ No newline at end of file diff --git a/.dev-suite/hooked/wrapper/applypatch-msg.sh b/.dev-suite/hooked/wrapper/applypatch-msg.sh new file mode 100755 index 0000000..9719401 --- /dev/null +++ b/.dev-suite/hooked/wrapper/applypatch-msg.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/applypatch-msg.py diff --git a/.dev-suite/hooked/wrapper/commit-msg.sh b/.dev-suite/hooked/wrapper/commit-msg.sh new file mode 100755 index 0000000..b1a3623 --- /dev/null +++ b/.dev-suite/hooked/wrapper/commit-msg.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/commit-msg.py diff --git a/.dev-suite/hooked/wrapper/post-applypatch.sh b/.dev-suite/hooked/wrapper/post-applypatch.sh new file mode 100755 index 0000000..741c689 --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-applypatch.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-applypatch.py diff --git a/.dev-suite/hooked/wrapper/post-checkout.sh b/.dev-suite/hooked/wrapper/post-checkout.sh new file mode 100755 index 0000000..a2b99fa --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-checkout.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-checkout.py diff --git a/.dev-suite/hooked/wrapper/post-commit.sh b/.dev-suite/hooked/wrapper/post-commit.sh new file mode 100755 index 0000000..6e392a4 --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-commit.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-commit.py diff --git a/.dev-suite/hooked/wrapper/post-merge.sh b/.dev-suite/hooked/wrapper/post-merge.sh new file mode 100755 index 0000000..8a6eda9 --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-merge.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-merge.py diff --git a/.dev-suite/hooked/wrapper/post-receive.sh b/.dev-suite/hooked/wrapper/post-receive.sh new file mode 100755 index 0000000..c8b87f9 --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-receive.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-receive.py diff --git a/.dev-suite/hooked/wrapper/post-rewrite.sh b/.dev-suite/hooked/wrapper/post-rewrite.sh new file mode 100755 index 0000000..fb41a73 --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-rewrite.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-rewrite.py diff --git a/.dev-suite/hooked/wrapper/post-update.sh b/.dev-suite/hooked/wrapper/post-update.sh new file mode 100755 index 0000000..f9e816d --- /dev/null +++ b/.dev-suite/hooked/wrapper/post-update.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/post-update.py diff --git a/.dev-suite/hooked/wrapper/pre-auto-gc.sh b/.dev-suite/hooked/wrapper/pre-auto-gc.sh new file mode 100755 index 0000000..2e1400c --- /dev/null +++ b/.dev-suite/hooked/wrapper/pre-auto-gc.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/pre-auto-gc.py diff --git a/.dev-suite/hooked/wrapper/pre-commit.sh b/.dev-suite/hooked/wrapper/pre-commit.sh new file mode 100755 index 0000000..196c797 --- /dev/null +++ b/.dev-suite/hooked/wrapper/pre-commit.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/pre-commit.py diff --git a/.dev-suite/hooked/wrapper/pre-push.sh b/.dev-suite/hooked/wrapper/pre-push.sh new file mode 100755 index 0000000..0d760d0 --- /dev/null +++ b/.dev-suite/hooked/wrapper/pre-push.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/pre-push.py diff --git a/.dev-suite/hooked/wrapper/pre-rebase.sh b/.dev-suite/hooked/wrapper/pre-rebase.sh new file mode 100755 index 0000000..642be35 --- /dev/null +++ b/.dev-suite/hooked/wrapper/pre-rebase.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/pre-rebase.py diff --git a/.dev-suite/hooked/wrapper/pre-receive.sh b/.dev-suite/hooked/wrapper/pre-receive.sh new file mode 100755 index 0000000..b33366f --- /dev/null +++ b/.dev-suite/hooked/wrapper/pre-receive.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/pre-receive.py diff --git a/.dev-suite/hooked/wrapper/prepare-commit-msg.sh b/.dev-suite/hooked/wrapper/prepare-commit-msg.sh new file mode 100755 index 0000000..e04c27b --- /dev/null +++ b/.dev-suite/hooked/wrapper/prepare-commit-msg.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/prepare-commit-msg.py diff --git a/.dev-suite/hooked/wrapper/push-to-checkout.sh b/.dev-suite/hooked/wrapper/push-to-checkout.sh new file mode 100755 index 0000000..47718bf --- /dev/null +++ b/.dev-suite/hooked/wrapper/push-to-checkout.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/push-to-checkout.py diff --git a/.dev-suite/hooked/wrapper/sendemail-validate.sh b/.dev-suite/hooked/wrapper/sendemail-validate.sh new file mode 100755 index 0000000..389deb1 --- /dev/null +++ b/.dev-suite/hooked/wrapper/sendemail-validate.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/sendemail-validate.py diff --git a/.dev-suite/hooked/wrapper/update.sh b/.dev-suite/hooked/wrapper/update.sh new file mode 100755 index 0000000..0d42ffd --- /dev/null +++ b/.dev-suite/hooked/wrapper/update.sh @@ -0,0 +1,2 @@ +#!C:\Program Files\Git\bin\sh.exe +py.exe .dev-suite/hooked/update.py diff --git a/hooked/src/main.rs b/hooked/src/main.rs index 7e33499..1c8388e 100644 --- a/hooked/src/main.rs +++ b/hooked/src/main.rs @@ -1,8 +1,9 @@ //! git hook manager tool -#[cfg(windows)] -use anyhow::bail; -use anyhow::Result; +use anyhow::{ + bail, + Result, +}; use log::*; use shared::find_root; #[cfg(not(windows))] @@ -16,6 +17,7 @@ use std::{ env, fs, io::Write, + path::Path, }; const HOOKS: [&str; 18] = [ @@ -41,8 +43,21 @@ const HOOKS: [&str; 18] = [ #[derive(structopt::StructOpt)] enum Args { - /// Initialize the repo to use ticket - Init, + /// Initialize the repo to use hooked + Init(Language), + /// Link pre existing hooks to your .git folder + Link, +} + +/// Which language the repo should be initialized with for hooks +#[derive(Clone, Copy, structopt::StructOpt)] +enum Language { + /// Use Bash for your git hooks + Bash, + /// Use Python 3 for your git hooks + Python, + /// Use Ruby for your git hooks + Ruby, } #[paw::main] @@ -52,60 +67,172 @@ fn main(args: Args) { .map_or_else(|| env::set_var("RUST_LOG", "info"), drop); pretty_env_logger::init(); if let Err(e) = match args { - Args::Init => init(), + Args::Init(lang) => init(lang), + Args::Link => link(), } { error!("{}", e); std::process::exit(1); } } -fn init() -> Result<()> { - #[cfg(windows)] - bail!("Windows is currently unsupported!"); - +fn init(lang: Language) -> Result<()> { let root = find_root()?; let git_hooks = &root.join(".git").join("hooks"); debug!("git_hooks base path: {}", git_hooks.display()); let root = root.join(".dev-suite").join("hooked"); debug!("root base path: {}", root.display()); - fs::create_dir_all(&root)?; + let wrapper_dir = &root.join("wrapper"); + fs::create_dir_all(&wrapper_dir)?; for hook in &HOOKS { - let path = &root.join(hook); + let mut path = (&root).join(hook); debug!("dev-suite hook path: {}", path.display()); let git_hook = &git_hooks.join(hook); debug!("git_hook path: {}", git_hook.display()); + let mut wrapper_hook = (&wrapper_dir).join(hook); + let _ = wrapper_hook.set_extension("sh"); + let _ = match lang { + Language::Bash => path.set_extension("sh"), + Language::Python => path.set_extension("py"), + Language::Ruby => path.set_extension("rb"), + }; if path.exists() { debug!("git hook {} already exists. Skipping creation.", hook); } else { debug!("Creating dev-suite hook."); let mut file = fs::File::create(&path)?; + let mut wrapper = fs::File::create(&wrapper_hook)?; trace!("File created."); - let mut perms = file.metadata()?.permissions(); - debug!("Setting dev-suite hook to be executable."); - perms.set_mode(0o755); - file.set_permissions(perms)?; - trace!("Permissions were set."); - file.write_all(b"#! /bin/bash")?; + #[cfg(not(windows))] + { + let mut perms = file.metadata()?.permissions(); + let mut wrapper_perms = wrapper.metadata()?.permissions(); + debug!("Setting dev-suite hook to be executable."); + perms.set_mode(0o755); + wrapper_perms.set_mode(0o755); + file.set_permissions(perms)?; + wrapper.set_permissions(wrapper_perms)?; + trace!("Permissions were set."); + } + match lang { + Language::Bash => { + file.write_all(b"#!/usr/bin/env bash")?; + wrapper.write_all( + format!( + "#!C:\\Program Files\\Git\\bin\\sh.exe\n\ + bash.exe .dev-suite/hooked/{}.sh\n", + hook + ) + .as_bytes(), + )?; + } + Language::Python => { + file.write_all(b"#!/usr/bin/env python3")?; + wrapper.write_all( + format!( + "#!C:\\Program Files\\Git\\bin\\sh.exe\n\ + py.exe .dev-suite/hooked/{}.py\n", + hook + ) + .as_bytes(), + )?; + } + Language::Ruby => { + file.write_all(b"#!/usr/bin/env ruby")?; + wrapper.write_all( + format!( + "#!C:\\Program Files\\Git\\bin\\sh.exe\n\ + ruby.exe .dev-suite/hooked/{}.rb\n", + hook + ) + .as_bytes(), + )?; + } + } debug!("Writing data to file."); debug!("Created git hook {}.", hook); } - let path = path.canonicalize()?; - if !git_hook.exists() { - debug!("Symlinking git hook {}.", hook); - #[cfg(not(windows))] - symlink(&path, &git_hook)?; - #[cfg(windows)] - symlink_file(&path, &git_hook)?; - trace!("Symlinked git hook {} to .dev-suite/hooked/{}.", hook, hook); - } + #[cfg(not(windows))] + let link_path = path.canonicalize()?; + #[cfg(windows)] + let link_path = wrapper_hook.canonicalize()?; + + inner_link(&link_path, &git_hook, hook)?; } info!( "Created and symlinked tickets to .git/hooks from {}.", root.display() ); + #[cfg(windows)] + { + warn!("Make sure to add the hooks into git with 'git add --chmod=+x .dev-suite\\hooked'"); + warn!("If you don't they won't be set as executable on unix systems"); + } + + Ok(()) +} + +fn link() -> Result<()> { + let root = find_root()?; + let git_hooks = &root.join(".git").join("hooks"); + debug!("git_hooks base path: {}", git_hooks.display()); + let root = root.join(".dev-suite").join("hooked"); + debug!("root base path: {}", root.display()); + + for hook in &HOOKS { + let path = { + #[cfg(windows)] + let mut path = root.join("wrapper").join(hook); + #[cfg(not(windows))] + let mut path = root.join(hook); + debug!("PATH: {}", path.display()); + let mut path_python = path.clone(); + let _ = path_python.set_extension("py"); + let mut path_ruby = path.clone(); + let _ = path_ruby.set_extension("rb"); + let mut path_bash = path.clone(); + let _ = path_bash.set_extension("sh"); + + if path_python.exists() { + path_python + } else if path_ruby.exists() { + path_ruby + } else if path_bash.exists() { + path_bash + } else { + let _ = path.set_extension(""); + bail!( + "The path {} does not exist. Have you initialized the repo to use hooked?", + path.display() + ); + } + }; + let path = path.canonicalize()?; + debug!("dev-suite hook path: {}", path.display()); + let git_hook = &git_hooks.join(hook); + debug!("git_hook path: {}", git_hook.display()); + inner_link(&path, &git_hook, hook)?; + } + + info!("Successfully symlinked all githooks to .git/hooks"); + Ok(()) +} + +fn inner_link(path: &Path, git_hook: &Path, hook: &str) -> Result<()> { + if !git_hook.exists() { + debug!("Symlinking git hook {}.", hook); + #[cfg(not(windows))] + symlink(&path, &git_hook)?; + #[cfg(windows)] + symlink_file(&path, &git_hook)?; + debug!( + "Symlinked git hook {} to {}", + git_hook.display(), + path.display() + ); + } Ok(()) } diff --git a/hooked/tests/init.rs b/hooked/tests/init.rs index 65c4aab..9c68ff3 100644 --- a/hooked/tests/init.rs +++ b/hooked/tests/init.rs @@ -1,10 +1,10 @@ use assert_cmd::prelude::*; use git2::Repository; +#[cfg(not(windows))] +use std::os::unix::fs::PermissionsExt; use std::{ - env, error::Error, fs, - os::unix::fs::PermissionsExt, process::Command, }; use tempfile::tempdir; @@ -30,19 +30,36 @@ const HOOKS: [&str; 18] = [ "sendemail-validate", ]; -#[test] -fn init() -> Result<(), Box> { +fn lang(lang: &str) -> Result<(), Box> { let dir = tempdir()?; let _ = Repository::init(&dir)?; - let mut cmd = Command::cargo_bin("hooked")?; - env::set_current_dir(&dir)?; - let _ = cmd.arg("init").assert().success(); + let _ = Command::cargo_bin("hooked")? + .arg("init") + .arg(lang) + .current_dir(&dir) + .assert() + .success(); let git = &dir.path().join(".git").join("hooks"); let dev = &dir.path().join(".dev-suite").join("hooked"); for hook in &HOOKS { let git_hook = git.join(hook); - let dev_hook = dev.join(hook); + #[cfg(not(windows))] + let mut dev_hook = dev.join(hook); + #[cfg(windows)] + let mut dev_hook = dev.join("wrapper").join(hook); + + #[cfg(not(windows))] + let _ = match lang { + "bash" => dev_hook.set_extension("sh"), + "python" => dev_hook.set_extension("py"), + "ruby" => dev_hook.set_extension("rb"), + _ => unreachable!(), + }; + + #[cfg(windows)] + let _ = dev_hook.set_extension("sh"); + assert!(&git_hook.exists()); assert!(&dev_hook.exists()); assert!(fs::symlink_metadata(&git_hook)?.file_type().is_symlink()); @@ -54,8 +71,39 @@ fn init() -> Result<(), Box> { // numbers essentially, allowing us to test the actual value we wanted to // test, and making this test work without special casing it if git ever // changes. + #[cfg(not(windows))] assert_eq!(dev_hook.metadata()?.permissions().mode() & 511, 0o755); - } + let shebang = fs::read_to_string(&dev_hook)? + .lines() + .nth(0) + .ok_or_else(|| "File is empty and has no shebang line")? + .to_owned(); + + #[cfg(not(windows))] + match lang { + "bash" => assert_eq!(shebang, "#!/usr/bin/env bash"), + "python" => assert_eq!(shebang, "#!/usr/bin/env python3"), + "ruby" => assert_eq!(shebang, "#!/usr/bin/env ruby"), + _ => unreachable!(), + } + #[cfg(windows)] + assert_eq!(shebang, "#!C:\\Program Files\\Git\\bin\\sh.exe") + } Ok(()) } + +#[test] +fn init_bash() -> Result<(), Box> { + lang("bash") +} + +#[test] +fn init_python() -> Result<(), Box> { + lang("python") +} + +#[test] +fn init_ruby() -> Result<(), Box> { + lang("ruby") +} -- cgit v1.2.3