+ (standard-cli "candle project" (project-options) args (project-usage) nil
+ (let
+ ((subcommand (intern (string-upcase (car remaining-args)) :keyword)))
+ (case subcommand
+ (:delete (delete-project (cdr remaining-args)))
+ (:add (add-project (cdr remaining-args)))
+ (:show (show-project (cdr remaining-args)))
+ (:refresh (refresh-project (cdr remaining-args)))
+ (:list (list-projects))
+ (:failures (project-failures (cdr remaining-args)))
+ (t (format t "~A" (project-usage)))))))
+
+(defun project-usage ()
+ (opera:usage
+ "candle project"
+ (project-options)
+ "Interacts with projects. The available project subcommands are:
+ list List all projects
+ add <name>:<src> Add a project
+ delete <name> Delete a project
+ show <name> Show project branch information
+ refresh <name> Tell the candle server to refresh the project information"))
+
+(defun project-options ()
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<subcommand>" :description "Project subcommand, see below.")))
+
+(defun add-project (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<name>:<src>" :description "<name> is the name of the project, which must be alphanumeric (hyphens are allowed), while <src> is the location of the repository for cloning. This location must be accessible by the machine running candle."))))
+ (standard-cli "candle project add" options args :default "<name>:<src>"
+ (let*
+ ((project-definition (car remaining-args))
+ (pos (position #\: project-definition)))
+ (cond
+ ((not pos) (format *error-output* "Project definition ~A is not valid. See 'candle project --help'.~%" project-definition))
+ (t
+ (let*
+ ((name (subseq project-definition 0 pos))
+ (src (subseq project-definition (1+ pos))))
+ (communication:query `(candle:add-project ,name ,src))
+ (format t "Added project ~A at src definition ~A~%" name src))))))))
+
+(defun delete-project (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<name>" :description "<name> is the name of the project to delete"))))
+ (standard-cli "candle project delete" options args :default "<name>"
+ (communication:query `(candle:delete-project ,(car remaining-args)))
+ (format t "Removed project ~A~%" (car remaining-args)))))
+
+(defun show-project (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<name>" :description "<name> is the name of the project to show"))))
+ (standard-cli "candle project show" options args :default "<name>"
+ (let*
+ ((branch-infos (communication:query `(candle:project-branch-information ,(car remaining-args))))
+ (width (apply #'max (mapcar #'length (mapcar #'car branch-infos)))))
+ (mapcar
+ (lambda (branch-info)
+ (format t (format nil "~~~A@A: ~~A~~%" width)
+ (first branch-info)
+ (job-info->line (second branch-info))))
+ (sort branch-infos #'< :key (lambda (branch-info) (third (second branch-info)))))))))
+
+(defun refresh-project (args)
+ (let
+ ((options
+ '((:name :help :short "h" :long "help" :description "Print this usage.")
+ (:positional "<name>" :description "<name> is the name of the project to refresh"))))
+ (standard-cli "candle project refresh" options args :default "<name>"
+ (communication:query `(candle:refresh-project ,(car remaining-args)))
+ (format t "Refreshed project ~A~%" (car remaining-args)))))
+
+(defun list-projects ()
+ (format t "~{~{~A ~A~}~%~}" (communication:query `(candle:list-projects))))
+
+(defun project-failures (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 failures to project named by PROJECT"))))
+ (standard-cli "candle project failures" options args :default nil
+ (format t "~A"
+ (communication:query
+ `(candle:failures ,(when (opera:option-present :project parsed-options) (opera:option-argument :project parsed-options))))))))
+
+;;; Section for ./candle job