pax_global_header00006660000000000000000000000064121145751010014507gustar00rootroot0000000000000052 comment=dff472f8e5c312d7fd70cc6ebccb215970089210 cl-github-v3-20130312-git/000077500000000000000000000000001211457510100147315ustar00rootroot00000000000000cl-github-v3-20130312-git/LICENSE000066400000000000000000000027601211457510100157430ustar00rootroot00000000000000Copyright (c) 2008-2012 Hans Huebner and contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name Hans Huebner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cl-github-v3-20130312-git/README.md000066400000000000000000000004021211457510100162040ustar00rootroot00000000000000# cl-github-v3 - Common Lisp interface to the github V3 API This library implements a thin wrapper around [github's V3 API](http://developer.github.com/). At this point, it is incomplete and only defines CL functions for listing and creating repositories. cl-github-v3-20130312-git/cl-github-v3.asd000066400000000000000000000003431211457510100176260ustar00rootroot00000000000000(defsystem :cl-github-v3 :serial t :version "0.0.1" :description "github V3 API library" :author "Hans Huebner" :depends-on (:drakma :yason :alexandria) :components ((:file "github"))) cl-github-v3-20130312-git/github.lisp000066400000000000000000000075611211457510100171150ustar00rootroot00000000000000(defpackage :cl-github (:nicknames :github) (:use #:cl) (:export #:*username* #:*password* #:api-command #:create-repository #:list-repositories)) (in-package #:cl-github) (defvar *username* nil "Username to use for API calls") (defvar *password* nil "Password to use for API calls") (define-condition api-error (error) ((http-status :initarg :http-status :reader error-http-status) (http-headers :initarg :http-headers :reader error-http-headers) (response :initarg :response :reader error-response)) (:report (lambda (c stream) (format stream "github API error, HTTP status code ~A~%~A~@[~%~A~]" (error-http-status c) (error-http-headers c) (error-response c))))) (defun keyword-to-github-keyword (keyword) (string-downcase (substitute #\_ #\- (string keyword)))) (defun github-keyword-to-keyword (string) (let ((*package* (find-package :keyword))) (read-from-string (substitute #\- #\_ string)))) (defun plist-to-http-parameters (plist) (loop for (key value) on plist by #'cddr collect (cons (keyword-to-github-keyword key) value))) (defun plist-to-hash-table (plist) (loop with hash-table = (make-hash-table :test #'equal) for (key value) on plist by #'cddr do (setf (gethash (keyword-to-github-keyword key) hash-table) value) finally (return hash-table))) (defun api-command (url &key body (method :get) (username *username*) (password *password*) parameters) (multiple-value-bind (body status-code headers) (drakma:http-request (format nil "https://api.github.com~A" url) :method method :parameters (plist-to-http-parameters parameters) :basic-authorization (when username (list username password)) :content-type "application/json" :content (when body (with-output-to-string (s) (yason:encode (plist-to-hash-table body) s)))) (let* ((yason:*parse-object-as* :plist) (yason:*parse-object-key-fn* 'github-keyword-to-keyword) (response (when body (yason:parse (flex:octets-to-string body :external-format :utf-8))))) (if (< status-code 300) (values response headers) (error 'api-error :http-status status-code :http-headers headers :response response))))) (defmacro booleanize-parameters (plist &rest keys) ;; unhygienic `(setf ,plist (let (result) (alexandria:doplist (key value ,plist (nreverse result)) (push key result) (push (if (member key ',keys) (if value "true" "false") value) result))))) (defmacro define-github-command (name parameters &body body) ;; unhygienic `(prog1 (defun ,name (&rest parameters &key ,@parameters) (declare (ignorable parameters ,@(loop for parameter in parameters collect (if (listp parameter) (first parameter) parameter)))) ,@body) (export ',name))) (define-github-command create-repository (name org description homepage public has-issues has-wiki has-downloads) (booleanize-parameters parameters :has-issues :has-wiki :has-downloads) (api-command (if org (format nil "/orgs/~A/repos" org) "/user/repos") :method :post :body parameters)) (define-github-command list-repositories (org) (api-command (if org (format nil "/orgs/~A/repos" org) "/user/repos") :method :get))