2016-02-24 22:06:01 +00:00
|
|
|
;;; gh-issues.el --- issues api for github
|
|
|
|
|
|
|
|
;; Copyright (C) 2012 Raimon Grau
|
|
|
|
|
|
|
|
;; Author: Raimon Grau <raimonster@gmail.com>
|
|
|
|
;; Keywords:
|
|
|
|
|
|
|
|
;; This program is free software; you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; Basic usage:
|
|
|
|
|
|
|
|
;; (setf api (gh-issues-api "api" :sync nil :cache nil :num-retries 1))
|
|
|
|
;; (setf issues (gh-issues-list api "user" "repo"))
|
|
|
|
;; (last (oref issues data)) ; get one issue
|
|
|
|
;; (setq mi (make-instance 'gh-issues-issue :body "issue body" :title "issue title"))
|
|
|
|
;; (gh-issues-issue-new api "user" "repo" mi)
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(eval-when-compile
|
|
|
|
(require 'cl))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(require 'eieio)
|
|
|
|
|
|
|
|
(require 'gh-api)
|
|
|
|
(require 'gh-auth)
|
|
|
|
(require 'gh-common)
|
|
|
|
|
|
|
|
(require 'gh-repos)
|
|
|
|
|
|
|
|
(defclass gh-issues-api (gh-api-v3)
|
|
|
|
((issue-cls :allocation :class :initform gh-issues-issue)
|
|
|
|
(milestone-cls :allocation :class :initform gh-issues-milestone)
|
|
|
|
(label-cls :allocation :class :initform gh-issues-label))
|
|
|
|
"Github Issues api")
|
|
|
|
|
|
|
|
(defclass gh-issues-issue (gh-object)
|
|
|
|
((url :initarg :url)
|
|
|
|
(html-url :initarg :html-url)
|
|
|
|
(number :initarg :number)
|
|
|
|
(state :initarg :state)
|
|
|
|
(title :initarg :title)
|
|
|
|
(body :initarg :body)
|
|
|
|
(user :initarg :user :initform nil)
|
|
|
|
(labels :initarg :labels :initform nil)
|
|
|
|
(assignee :initarg :assignee :initform nil)
|
|
|
|
(milestone :initarg :milestone :initform nil)
|
|
|
|
(open_issues :initarg :open_issues)
|
|
|
|
(closed_issues :initarg :closed_issues)
|
|
|
|
(created_at :initarg :created_at)
|
|
|
|
(due_on :initarg :due_on)
|
|
|
|
|
|
|
|
(user-cls :allocation :class :initform gh-user)
|
|
|
|
(milestone-cls :allocation :class :initform gh-issues-milestone))
|
|
|
|
"issues request")
|
|
|
|
|
|
|
|
(defclass gh-issues-label (gh-object)
|
|
|
|
((url :initarg :url)
|
|
|
|
(name :initarg :name)
|
|
|
|
(color :initarg :color)))
|
|
|
|
|
|
|
|
(defclass gh-issues-milestone (gh-object)
|
|
|
|
((url :initarg :url)
|
|
|
|
(number :initarg :number)
|
|
|
|
(state :initarg :state)
|
|
|
|
(title :initarg :title)
|
|
|
|
(description :initarg :description)
|
|
|
|
(creator :initarg :creator :initform nil)
|
|
|
|
(open_issues :initarg :open_issues)
|
|
|
|
(closed_issues :initarg :closed_issues)
|
|
|
|
(created_at :initarg :created_at)
|
|
|
|
(due_on :initarg :due_on)
|
|
|
|
|
|
|
|
(user-cls :allocation :class :initform gh-user))
|
|
|
|
"github milestone")
|
|
|
|
|
|
|
|
(defmethod gh-object-read-into ((issue gh-issues-issue) data)
|
|
|
|
(call-next-method)
|
|
|
|
(with-slots (url html-url number state title body
|
|
|
|
user labels assignee milestone open_issues
|
|
|
|
closed_issues created_at due_on)
|
|
|
|
issue
|
|
|
|
(setq url (gh-read data 'url)
|
|
|
|
html-url (gh-read data 'html_url)
|
|
|
|
number (gh-read data 'number)
|
|
|
|
state (gh-read data 'state)
|
|
|
|
title (gh-read data 'title)
|
|
|
|
body (gh-read data 'body)
|
|
|
|
user (gh-object-read (or (oref issue :user)
|
|
|
|
(oref issue user-cls))
|
|
|
|
(gh-read data 'user))
|
|
|
|
labels (gh-read data 'labels)
|
|
|
|
assignee (gh-object-read (or (oref issue :assignee)
|
|
|
|
(oref issue user-cls))
|
|
|
|
(gh-read data 'assignee))
|
|
|
|
milestone (gh-object-read (or (oref issue :milestone)
|
|
|
|
(oref issue milestone-cls))
|
|
|
|
(gh-read data 'milestone))
|
|
|
|
open_issues (gh-read data 'open_issues)
|
|
|
|
closed_issues (gh-read data 'closed_issues)
|
|
|
|
created_at (gh-read data 'created_at)
|
|
|
|
due_on (gh-read data 'due_on))))
|
|
|
|
|
|
|
|
|
|
|
|
(defmethod gh-object-read-into ((milestone gh-issues-milestone) data)
|
|
|
|
(call-next-method)
|
|
|
|
(with-slots (url number state title description creator
|
|
|
|
open_issues closed_issues
|
|
|
|
created_at due_on)
|
|
|
|
milestone
|
|
|
|
(setq url (gh-read data 'url)
|
|
|
|
number (gh-read data 'number)
|
|
|
|
state (gh-read data 'state)
|
|
|
|
title (gh-read data 'title)
|
|
|
|
description (gh-read data 'description)
|
|
|
|
creator (gh-object-read (or (oref milestone :creator)
|
|
|
|
(oref milestone user-cls))
|
|
|
|
(gh-read data 'creator))
|
|
|
|
|
|
|
|
open_issues (gh-read data 'open_issues)
|
|
|
|
closed_issues (gh-read data 'closed_issues)
|
|
|
|
created_at (gh-read data 'created_at)
|
|
|
|
due_on (gh-read data 'due_on))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-issue-list ((api gh-issues-api) user repo)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api issue-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/issues" user repo)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-milestone-list ((api gh-issues-api) user repo)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api milestone-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/milestones" user repo)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-milestone-get ((api gh-issues-api) user repo id)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api milestone-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/milestones/%s" user repo id)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-milestone-new ((api gh-issues-api) user repo milestone)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api milestone-cls)) "POST"
|
|
|
|
(format "/repos/%s/%s/milestones" user repo)
|
|
|
|
(gh-issues-milestone-req-to-update milestone)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-milestone-update ((api gh-issues-api) user repo
|
|
|
|
id milestone)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api milestone-cls)) "PATCH"
|
|
|
|
(format "/repos/%s/%s/milestones/%s" user repo id)
|
|
|
|
(gh-issues-milestone-req-to-update milestone)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-milestone-req-to-update ((milestone gh-issues-milestone))
|
2016-06-29 07:21:54 +00:00
|
|
|
(let ((state (oref milestone :state))
|
|
|
|
(description (oref milestone :description))
|
|
|
|
(due-on (oref milestone :due-on))
|
|
|
|
(to-update `(("title" . ,(oref milestone :title)))))
|
2016-02-24 22:06:01 +00:00
|
|
|
(when state (nconc to-update `(("state" . ,state))))
|
|
|
|
(when description (nconc to-update `(("description" . ,description))))
|
2016-06-29 07:21:54 +00:00
|
|
|
(when due-on (nconc to-update `(("due_on" . ,due-on))))
|
2016-02-24 22:06:01 +00:00
|
|
|
to-update))
|
|
|
|
|
|
|
|
(defmethod gh-issues-issue-get ((api gh-issues-api) user repo id)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api issue-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/issues/%s" user repo id)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-issue-req-to-update ((req gh-issues-issue))
|
2016-06-29 07:21:54 +00:00
|
|
|
(let ((assignee (oref req :assignee))
|
2016-02-24 22:06:01 +00:00
|
|
|
;; (labels (oref req labels))
|
2016-06-29 07:21:54 +00:00
|
|
|
(milestone (oref req :milestone))
|
|
|
|
(to-update `(("title" . ,(oref req :title))
|
|
|
|
("state" . ,(oref req :state))
|
|
|
|
("body" . ,(oref req :body)))))
|
2016-02-24 22:06:01 +00:00
|
|
|
|
|
|
|
;; (when labels (nconc to-update `(("labels" . ,(oref req labels) ))))
|
|
|
|
(when milestone
|
2016-06-29 07:21:54 +00:00
|
|
|
(nconc to-update `(("milestone" . ,(oref milestone :number)))))
|
2016-02-24 22:06:01 +00:00
|
|
|
(when assignee
|
2016-06-29 07:21:54 +00:00
|
|
|
(nconc to-update `(("assignee" . ,(oref assignee :login)))))
|
2016-02-24 22:06:01 +00:00
|
|
|
to-update))
|
|
|
|
|
|
|
|
(defmethod gh-issues-issue-update ((api gh-issues-api) user repo id req)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api issue-cls)) "PATCH"
|
|
|
|
(format "/repos/%s/%s/issues/%s" user repo id)
|
|
|
|
(gh-issues-issue-req-to-update req)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-issue-new ((api gh-issues-api) user repo issue)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api issue-cls)) "POST"
|
|
|
|
(format "/repos/%s/%s/issues" user repo)
|
|
|
|
(gh-issues-issue-req-to-update issue)))
|
|
|
|
|
|
|
|
;;; labels
|
|
|
|
(defclass gh-issues-label (gh-object)
|
|
|
|
((url :initarg :url)
|
|
|
|
(name :initarg :name)
|
|
|
|
(color :initarg :color)))
|
|
|
|
|
|
|
|
(defmethod gh-object-read-into ((label gh-issues-label) data)
|
|
|
|
(call-next-method)
|
|
|
|
(with-slots (url name color)
|
|
|
|
label
|
|
|
|
(setq url (gh-read data 'url)
|
|
|
|
name (gh-read data 'name)
|
|
|
|
color (gh-read data 'color))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-req-to-update ((label gh-issues-label))
|
|
|
|
`(("name" . ,(oref label name))
|
|
|
|
("color" . ,(oref label color))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-get ((api gh-issues-api) user repo name)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api label-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/labels/%s" user repo name)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-list ((api gh-issues-api) user repo)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api label-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/labels" user repo )))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-new ((api gh-issues-api) user repo req)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api label-cls)) "POST"
|
|
|
|
(format "/repos/%s/%s/labels" user repo)
|
|
|
|
(gh-issues-label-req-to-update req)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-update ((api gh-issues-api) user repo req)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api label-cls)) "POST"
|
2016-06-29 07:21:54 +00:00
|
|
|
(format "/repos/%s/%s/labels/%s" user repo (oref req :name))
|
2016-02-24 22:06:01 +00:00
|
|
|
(gh-issues-label-req-to-update req)))
|
|
|
|
|
|
|
|
(defmethod gh-issues-label-delete ((api gh-issues-api) user repo name)
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-reader (oref api label-cls)) "DELETE"
|
|
|
|
(format "/repos/%s/%s/labels/%s" user repo name)))
|
|
|
|
|
|
|
|
|
|
|
|
(defmethod gh-issues-labels-in-issue ((api gh-issues-api) user repo
|
|
|
|
issue-or-issue-id)
|
|
|
|
(let ((issue-id (gh-issues--issue-id issue-or-issue-id)))
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api label-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/issues/%s/labels" user repo issue-id))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-labels-add-to-issue ((api gh-issues-api) user repo
|
|
|
|
issue-or-issue-id labels)
|
|
|
|
(let ((issue-id (gh-issues--issue-id issue-or-issue-id)))
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api label-cls)) "PUT"
|
|
|
|
(format "/repos/%s/%s/issues/%s/labels" user repo issue-id)
|
|
|
|
(mapcar #'gh-issues--label-name labels))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-labels-remove-all-from-issue ((api gh-issues-api) user repo
|
|
|
|
issue-or-issue-id )
|
|
|
|
(let ((issue-id (gh-issues--issue-id issue-or-issue-id)))
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (lambda (x) x) "DELETE"
|
|
|
|
(format "/repos/%s/%s/issues/%s/labels" user repo issue-id))))
|
|
|
|
|
|
|
|
(defmethod gh-issues-labels-in-milestone ((api gh-issues-api) user repo
|
|
|
|
milestone-or-milestone-id)
|
|
|
|
(let ((milestone-id (gh-issues--milestone-id milestone-or-milestone-id)))
|
|
|
|
(gh-api-authenticated-request
|
|
|
|
api (gh-object-list-reader (oref api label-cls)) "GET"
|
|
|
|
(format "/repos/%s/%s/milestones/%s/labels" user repo milestone-id))))
|
|
|
|
|
|
|
|
|
|
|
|
;;; helpers
|
|
|
|
|
|
|
|
(defun gh-issues--issue-id (issue-or-issue-id)
|
|
|
|
(if (eieio-object-p issue-or-issue-id)
|
2016-06-29 07:21:54 +00:00
|
|
|
(oref issue-or-issue-id :id)
|
2016-02-24 22:06:01 +00:00
|
|
|
issue-or-issue-id))
|
|
|
|
|
|
|
|
(defun gh-issues--milestone-id (milestone-or-milestone-id)
|
|
|
|
(if (eieio-object-p milestone-or-milestone-id)
|
2016-06-29 07:21:54 +00:00
|
|
|
(oref milestone-or-milestone-id :id)
|
2016-02-24 22:06:01 +00:00
|
|
|
milestone-or-milestone-id))
|
|
|
|
|
|
|
|
(defun gh-issues--label-name (label-or-label-name)
|
|
|
|
(if (eieio-object-p label-or-label-name)
|
2016-06-29 07:21:54 +00:00
|
|
|
(oref label-or-label-name :name)
|
2016-02-24 22:06:01 +00:00
|
|
|
label-or-label-name))
|
|
|
|
|
|
|
|
|
|
|
|
(provide 'gh-issues)
|
|
|
|
;;; gh-issues.el ends here
|
|
|
|
|
|
|
|
;; Local Variables:
|
|
|
|
;; indent-tabs-mode: nil
|
|
|
|
;; End:
|