+(defun job-list (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:name :project :long "project" :variable-name "PROJECT" :takes-argument t
+ :description "Restrict jobs to project named by PROJECT"))))
+ (standard-cli "candle job list" options args :default nil
+ (format t "~{~A~%~}"
+ (mapcar
+ #'job-info->line
+ (sort
+ (communication:query `(candle:project-job-information ,(opera:option-argument :project parsed-options)))
+ #'< :key #'fourth))))))
+
+(defun decompose-job-definition (job-definition)
+ (let
+ ((pos (position #\: job-definition)))
+ (when
+ pos
+ (values
+ (subseq job-definition 0 pos)
+ (subseq job-definition (1+ pos))))))
+
+(defun job-log (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<project>:<sha>"
+ :description "<project> is the name of the project, while <sha> is the sha of the job in question."))))
+ (standard-cli "candle job log" options args :default "<project>:<sha>"
+ (multiple-value-bind (project-name sha) (decompose-job-definition (car remaining-args))
+ (if project-name
+ (format t "~A" (communication:query `(candle:get-job-log ,project-name ,sha)))
+ (error-and-exit "Job definition ~A is not valid. See 'candle job log --help'.~%" (car remaining-args)))))))
+
+(defun retry-job (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<project>:<sha>"
+ :description "<project> is the name of the project, while <sha> is the sha of the job in question."))))
+ (standard-cli "candle job retry" options args :default "<project>:<sha>"
+ (multiple-value-bind (project-name sha) (decompose-job-definition (car remaining-args))
+ (if project-name
+ (progn
+ (communication:query `(candle:retry-job ,project-name ,sha))
+ (format t "Retrying job ~A~%" (car remaining-args)))
+ (error-and-exit "Job definition ~A is not valid. See 'candle job log --help'.~%" (car remaining-args)))))))