Add project deletion
[candle] / src / main / cli.lisp
1 (in-package #:candle-cli)
2
3 (defun main-options ()
4  '((:name :help :short "h" :long "help" :description "Print this usage.")
5    (:name :port :short "p" :long "port" :takes-argument t :variable-name "PORT"
6     :description "Port on which to listen for commands.  Defaults to 25004")
7    (:positional "<command>" :required t :description "Command to send to candle server")))
8
9 (defun project-options ()
10  '((:name :help :short "h" :long "help" :description "Print this usage.")
11    (:name :add :long "add" :takes-argument t :description
12     "Add a project.  NAME is the name of the project, which must not include colons, while SRC is the location of the repository for cloning.  This location must be accessible by the machine running candle."
13     :variable-name "NAME:SRC")
14    (:name :delete :long "delete" :takes-argument t :description
15     "Delete a project named by NAME."
16     :variable-name "NAME")))
17
18 (defun job-options ()
19  '((:name :help :short "h" :long "help" :description "Print this usage.")
20    (:name :project-name :long "project" :takes-argument t :description "The project name for the jobs under consideration.")
21    (:name :add :long "add" :takes-argument t :description
22     "Add a job to a project.  <sha> is the commit for that project to run the job.  Requires --project to be specified."
23     :variable-name "<sha>")))
24
25 (defun run-options ()
26  '((:name :help :short "h" :long "help" :description "Print this usage.")))
27
28 (defun main-usage ()
29  (format t "~A"
30   (opera:usage
31    "candle"
32    (main-options)
33    "Interacts with candle server.  The available commands are:
34   project   List, show or add projects
35   job       List or show jobs
36   run       Local command.  Run candle in the current working directory")))
37
38 (defgeneric execute-command (command args))
39
40 (defmethod execute-command (command args)
41  (format *error-output* "Unknown command '~(~A~)'.  See 'candle --help'.~%" command))
42
43 (defun add-project (project-definition)
44  (let
45   ((pos (position #\: project-definition)))
46   (cond
47    ((not pos) (format *error-output* "Project definition ~A is not valid.  See 'candle project --help'.~%" project-definition))
48    (t
49     (let*
50      ((name (subseq project-definition 0 pos))
51       (src (subseq project-definition (1+ pos))))
52      (communication:query `(candle:add-project ,name ,src))
53      (format t "Added project ~A at src definition ~A~%" name src))))))
54
55 (defun delete-project (name)
56  (communication:query `(candle:delete-project ,name))
57  (format t "Removed project ~A~%" name))
58
59 (defmethod execute-command ((command (eql :project)) args)
60  (multiple-value-bind (options remaining-args error) (opera:process-arguments (project-options) args)
61   (cond
62    ((eql error :unknown-option) (format *error-output* "Unknown option: ~A.  See 'candle project --help'.~%" (car remaining-args)))
63    ((eql error :required-argument-missing) (format *error-output* "Missing argument for ~A.  See 'candle project --help'.~%" (car remaining-args)))
64    ((opera:option-present :help options) (format t "~A" (opera:usage "candle project" (project-options))))
65    ((opera:option-present :delete options) (delete-project (opera:option-argument :delete options)))
66    ((opera:option-present :add options) (add-project (opera:option-argument :add options))))))
67
68 (defun add-job (project-name sha)
69  (format t "Added job with sha ~A to project ~A~%" sha project-name))
70
71 (defmethod execute-command ((command (eql :job)) args)
72  (multiple-value-bind (options remaining-args error) (opera:process-arguments (job-options) args)
73   (cond
74    ((eql error :unknown-option) (format *error-output* "Unknown option: ~A.  See 'candle job --help'.~%" (car remaining-args)))
75    ((eql error :required-argument-missing) (format *error-output* "Missing argument for ~A.  See 'candle job --help'.~%" (car remaining-args)))
76    ((opera:option-present :help options) (format t "~A" (opera:usage "candle job" (job-options))))
77    ((and (opera:option-present :add options) (not (opera:option-present :project-name options)))
78     (format *error-output* "Cannot --add without --project.  See 'candle job --help'.~%"))
79    ((opera:option-present :add options)
80     (add-job
81      (opera:option-argument :project-name options)
82      (opera:option-argument :add options))))))
83
84 (defmethod execute-command ((command (eql :run)) args)
85  (multiple-value-bind (options remaining-args error) (opera:process-arguments (run-options) args)
86   (cond
87    ((eql error :unknown-option) (format *error-output* "Unknown option: ~A.  See 'candle run --help'.~%" (car remaining-args)))
88    ((eql error :required-argument-missing) (format *error-output* "Missing argument for ~A.  See 'candle run --help'.~%" (car remaining-args)))
89    (remaining-args (format *error-output* "Unknown option: ~A. See 'candle run --help'.~%" (car remaining-args)))
90    ((opera:option-present :help options) (format t "~A" (opera:usage "candle run" (run-options))))
91    ((not (candle:run)) (sb-ext:exit :code 1)))))
92
93 (defun run ()
94  (multiple-value-bind (options remaining-args error) (opera:process-arguments (main-options) (cdr sb-ext:*posix-argv*))
95   (cond
96    ((opera:option-present :help options) (main-usage))
97    ((eql error :unknown-option) (format *error-output* "Unknown option: ~A.  See 'candle --help'.~%" (car remaining-args)))
98    ((and (opera:option-present :port options) (not (parse-integer (opera:option-argument :port options) :junk-allowed t)))
99     (format *error-output* "--port requires a number.  See 'candle-server -h'~%"))
100    ((not remaining-args) (format *error-output* "Command required.  See 'candle --help'.~%"))
101    (t
102     (let
103      ((communication:*query-port*
104        (or
105         (and
106          (opera:option-present :port options)
107          (parse-integer (opera:option-argument :port options) :junk-allowed t))
108         25004)))
109      (execute-command (intern (string-upcase (car remaining-args)) :keyword) (cdr remaining-args)))))))