Created
January 14, 2022 10:26
-
-
Save mateiidavid/a7ded6282ee576359b1214688ade610a to your computer and use it in GitHub Desktop.
Hacky Lua script to confirm any pushes to your main (or protected) git branch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/lua | |
--[[ | |
+-------------------+ | |
+ Lua pre-push hook + | |
+-------------------+ | |
- Prompts user to confirm remote pushes when working on a | |
protected branch and pushing to a _protected_ branch. | |
- Can be installed locally or globally. I usually | |
keep my config files in a dedicated directory and | |
create symlinks. | |
- Locally: you can place the file in your .git/hooks/pre-push | |
- Globally: create a directory for your hooks, e.g | |
~/.git/hooks and add it to your global .gitconfig | |
under [core]. | |
e.g vim ~/.gitconfig | |
+ [core] | |
+ hooksPath = /home/matei/.git/hooks | |
- chmod +x pre-push | |
- You can add your own protected branches (or repositories) to the | |
respective maps. If you want it enabled by default, delete the | |
repository logic. | |
- I left all my comments in, on the off chance that they're helpful. | |
NOTE: you need to have a lua interpreter installed to execute this! | |
https://www.lua.org/pil/1.4.html | |
Last but not least, I'm still learning Lua, this is just a hacky script! :) | |
--]] | |
-- I think technically this will only work if we're on that branch? | |
-- gotta RTFM. | |
local CMD_GIT_BRANCH = 'git rev-parse --abbrev-ref HEAD' | |
local CMD_GIT_REPO = 'git rev-parse --show-toplevel' | |
local PROTECTED_BRANCHES = {['main'] = true, ['master'] = true, ['add-git-hook'] = true} | |
local PROTECTED_REPOS = {['linkerd2'] = true, ['linkerd2-proxy'] = true, ['dotfiles'] = true} | |
local ANSI_RED = "\27[31m" | |
local ANSI_RESET = "\27[0m" | |
local ANSI_WHITE_BOLD = "\27[37;1;4m" -- 4 is for underline | |
local ANSI_BOLD = "\27[1m" | |
local ANSI_GREEN = "\27[32m" | |
local HOOK_NAME = "\27[96;4m[git-push-hook-check]\27[0m " | |
-- Execute takes in a command as a string and calls out into the shell to | |
-- execute it. We start a sub process using `io.popen` and then use the handle | |
-- to read the output from the command. | |
local function execute(command) | |
local handle = assert(io.popen(command)) | |
-- `*a` reads it all | |
-- https://www.lua.org/manual/5.1/manual.html#pdf-file:read | |
local output = handle:read("*a") | |
handle:close() | |
return output | |
end | |
-- Try execute will execute a command via a protected call (pcall). Pcall | |
-- will return a success boolean and an error message if the inner call | |
-- fails. We use it to bubble up errors, e.g socket errors from subprocs. | |
-- If the call fails, we exit with an error, otherwise, we return the output | |
-- from 'execute'. | |
local function try_execute(command) | |
local success, data = pcall(execute, command) | |
if not success then | |
os.exit(2) | |
end | |
return data | |
end | |
local repo_path = try_execute(CMD_GIT_REPO) | |
-- Will capture string after last '/' to get the name of the repository. | |
local repo_name = string.match(repo_path, "/%a+/.+/(%a+)") | |
if not PROTECTED_REPOS[repo_name] then | |
os.exit() | |
end | |
local branch_name = try_execute(CMD_GIT_BRANCH) | |
branch_name = string.gsub(branch_name, '\n', '') | |
if PROTECTED_BRANCHES[branch_name] then | |
-- colors! | |
local push_msg = HOOK_NAME..ANSI_GREEN.."\27[4;1mSure\27[0;32m you want to push to ["..ANSI_WHITE_BOLD..branch_name..ANSI_RESET..ANSI_GREEN.."]?"..ANSI_RESET..ANSI_BOLD.." (Y/n)"..ANSI_RESET | |
local confirm | |
repeat | |
print(push_msg) | |
-- Take input from controlling terminal | |
local tty_handle = io.open("/dev/tty") | |
confirm = tty_handle:read(1) | |
if not confirm then return end -- no input | |
confirm = confirm:lower() | |
until confirm == "y" or confirm == "n" | |
if confirm ~= "y" then | |
print(HOOK_NAME..ANSI_RED.."Push to ["..ANSI_WHITE_BOLD..branch_name..ANSI_RESET..ANSI_RED.."] aborted"..ANSI_RESET) | |
os.exit(1) | |
end | |
return | |
end | |
os.exit() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment