Skip to content

Instantly share code, notes, and snippets.

@Neronus
Created March 29, 2012 14:39
Show Gist options
  • Save Neronus/2238044 to your computer and use it in GitHub Desktop.
Save Neronus/2238044 to your computer and use it in GitHub Desktop.
pre-commit hook in lisp
#!lisp --script
(defpackage cve.pre-commit
(:use :cl :named-readtables :clesh :alexandria))
(in-package cve.pre-commit)
(in-readtable clesh:syntax)
(defvar *interactive* nil
"Indicates if we should drop into a debugger if an error (T)
occurs or if we should just exit the program with a non-zero value (NIL).")
(defvar *set-up-p* nil
"Did we already prepare the git repository?")
(defun set-up ()
"Prepare repository to be in the state it would have after the commit.
Call TEAR-DOWN to reset.
Signals an error if set-up is called twice without tear-down."
(when *set-up-p*
(error "set-up called twice without tear-down"))
(or-exit [ git stash --keep-index ])
(setf *set-up-p* t))
(defun tear-down ()
"Reset repository to the state it had before calling SET-UP.
Only to be called after a call to SET-UP."
(when (not *set-up-p*)
(error "tear-down without set-up called"))
(or-exit [ git stash pop ])
(setf *set-up-p* nil))
(defun exit (code)
"Exit program with exit-code CODE. Makes sure that git repository
is in the state it was in before the program started."
(when *set-up-p*
(tear-down))
(sb-ext:quit :unix-status code))
(defmacro or-exit (script)
"Run SCRIPT (which is expected to be a clesh:script command;
can also come from [ ... ] syntax).
If the return value is ZERO, just return all the values of SCRIPT.
Otherwise and if *INTERACTIVE* is NIL, call EXIT.
Otherwise signal an error."
(with-gensyms (stdout stderr code string)
`(multiple-value-bind (,stdout ,stderr ,code) ,script
(if (not (zerop ,code))
(let
((,string (concatenate 'string ,@(cdr script))))
(if *interactive*
(error "~A returned non-zero value" ,string)
(progn
(write-string ,stdout)
(format t "~A returned non-zero value~%"
,string)
(exit ,code))))
(values ,stdout ,stderr ,code)))))
(defun check-make (directory)
"Enter DIRECTORY and call make. Exit with Exit-code of make,
if its exit code was not zero. Returns the values of its
internal script otherwise."
(or-exit
[ cd ?directory
make 2>&1
exit $\?]))
(defparameter *make-files*
'("$HOME/Work/git/Papers/Repair/"))
(defun main ()
(set-up)
(dolist (make *make-files*)
(format t "Checking make for ~A~%" make)
(check-make make))
(exit 0))
(unless *interactive* (main))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment