diff options
| -rw-r--r-- | Makefile | 11 | ||||
| -rw-r--r-- | src/main.lisp | 28 | ||||
| -rw-r--r-- | src/option.lisp | 104 | ||||
| -rw-r--r-- | wajir.asd | 7 | 
4 files changed, 136 insertions, 14 deletions
| diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..03dbb2c --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +LISP ?= sbcl + + +.PHONY: build +build: wajir + +wajir: wajir.asd lib/* src/*.lisp +	$(LISP) --load wajir.asd \ +		--eval '(ql:quickload :wajir)' \ +		--eval '(asdf:make :wajir)' \ +		--eval '(quit)' diff --git a/src/main.lisp b/src/main.lisp index 2ac7daf..938a950 100644 --- a/src/main.lisp +++ b/src/main.lisp @@ -7,14 +7,18 @@    ;; Send email to ^maildir^program^ containing message with issue metadata    ;; Continue to next page -  (let ((config (make-instance 'config -                                :login "name@example.com" -                                :token "atlassian-token" -                                :endpoint "example.atlassian.net" -                                :email-to "name@example.com" -                                :jql "project = \"FAKE\" AND watcher != currentUser() AND key > \"FAKE-100\" ORDER BY created DESC"))) - -    (run config))) +  (let ((config (parse-options))) +    (format t "~S" config)) + +  ; (let ((config (make-instance 'config +  ;                               :login "name@example.com" +  ;                               :token "atlassian-token" +  ;                               :endpoint "example.atlassian.net" +  ;                               :email-to "name@example.com" +  ;                               :jql "project = \"FAKE\" AND watcher != currentUser() AND key > \"FAKE-100\" ORDER BY created DESC"))) +  ; +  ;   (run config)) +    )  (defun run (config)    (let ((basic-auth-token (cl-base64:string-to-base64-string @@ -89,10 +93,10 @@    (when (verbose config)      (format t "Watching issue ~A~%" (gethash "key" issue))) -  (add-watcher -    (endpoint config) -    issue -    :basic-auth-token basic-auth-token) +  ; (add-watcher +  ;   (endpoint config) +  ;   issue +  ;   :basic-auth-token basic-auth-token)    (if (sendmail config)        (deliver-email config issue))) diff --git a/src/option.lisp b/src/option.lisp new file mode 100644 index 0000000..4d1ce19 --- /dev/null +++ b/src/option.lisp @@ -0,0 +1,104 @@ +(in-package :wajir) + +(opts:define-opts +  (:name :login +   :description "Jira login email address" +   :long "login" +   :arg-parser #'identity +   :meta-var "<login>") +  (:name :token +   :description "Jira API token" +   :long "token" +   :arg-parser #'identity +   :meta-var "<token>") +  (:name :endpoint +   :description "Jira site URL host (e.g. example.atlassian.net)" +   :long "endpoint" +   :meta-var "<endpoint>") + +  (:name :sendmail +   :description "send email command" +   :long "sendmail" +   :meta-var "<command>") +  (:name :email-to +   :description "recipient email address" +   :long "email-to" +   :meta-var "<address>") + +  (:name :verbose +   :description "print verbose output" +   :short #\v +   :long "verbose") + +  (:name :help +   :description "print this help menu" +   :short #\h +   :long "help") +  (:name :version +   :description "show the program version" +   :short #\V +   :long "version")) + +(defmacro when-option ((options option) &body body) +  "When `option` is present in `options`, run `body`." +  `(let ((value (getf ,options ,option))) +     (when value +       ,@body))) + +(defun exit-with-error (condition exit-code) +  "Print the error associated with `condition` on standard error, then exit +with code `exit-code`." +  (format *error-output* "error: ~a~%" condition) + +  (opts:exit exit-code)) + +(defun handle-option-error (condition) +  "Handle errors related to command line options. Prints the error specified by +`condition` and exits with EX_USAGE." +  (exit-with-error condition sysexits:+usage+)) + +(defun parse-options () +  "Parse command line options." +  (multiple-value-bind (options free-args) +    (handler-bind +      ((opts:unknown-option #'handle-option-error) +       (opts:missing-arg #'handle-option-error) +       (opts:arg-parser-failed #'handle-option-error) +       (opts:missing-required-option #'handle-option-error)) + +      (opts:get-opts)) + +    ;; Help +    (when-option (options :help) +      (opts:describe +        :usage-of "wajir" +        :args "<JQL>") + +      (opts:exit sysexits:+usage+)) + +    ;; Version +    (when-option (options :version) +      (format t "~a~%" (asdf:component-version (asdf:find-system :extreload))) + +      (opts:exit sysexits:+ok+)) + +    ;; If `sendmail` is given, `email-to` must be defined. +    (when (not (null (getf options :sendmail))) +      (when (null (getf options  :email-to)) +        (format *error-output* "error: `--sendmail' requires `--email-to'") +        (opts:exit sysexits:+usage+))) + +    ;; Error if JQL is empty +    (when (null free-args) +      (format *error-output* "error: missing JQL") + +      (opts:exit sysexits:+usage+)) + +    (make-instance 'config +                   :login (getf options :login) +                   :token (getf options :token) +                   :endpoint (getf options :endpoint) +                   :sendmail (getf options :sendmail) +                   :email-to (getf options :email-to) +                   :verbose (getf options :verbose) +                   :jql (first free-args)))) @@ -13,17 +13,20 @@    :depends-on (:cl-base64                 :cl-smtp                 :com.inuoe.jzon -               :dexador) +               :dexador +               :sysexits +               :unix-opts)    :components ((:module "src"                  :serial t                  :components ((:file "package")                               (:file "config") +                             (:file "option")                               (:file "email")                               (:file "main"))))    :build-operation "program-op"    :build-pathname "wajir" -  :entry-point "wajir") +  :entry-point "wajir:main")  #+sb-core-compression  (defmethod asdf:perform ((o asdf:image-op) (c asdf:system)) | 
