Skip to content

Instantly share code, notes, and snippets.

@PuercoPop
Last active August 29, 2015 14:13
Show Gist options
  • Save PuercoPop/a5f36d42dd2a7997b2a9 to your computer and use it in GitHub Desktop.
Save PuercoPop/a5f36d42dd2a7997b2a9 to your computer and use it in GitHub Desktop.
(defpackage #:ngit
(:use :cl :chipz :babel))
(in-package #:ngit)
(defun from-first-space (string)
(subseq string (1+ (position #\Space string))))
(defclass git-repo ()
((path :initarg :path :reader path)))
(defclass git-obj ()
((id :initarg id :reader id :documentation "The hash of the obj contents.")
(size :initarg :size)))
(defclass commit (git-obj)
((tree :initarg :tree :reader tree
:documentation "The hash of the tree obj that contains the snapshot of
the tree.")
(parent :initarg :parent :reader parent
:documentation "The hash of the parent object")
(author :initarg :author :reader author
:documentation "Ignoring the date for now.")
(committer :initarg :committer :reader committer)
(commit-message :initarg :commit-message :reader commit-message)))
(defclass tree ()
())
(defclass blob ()
((size :initarg :size)
(content :initarg :content)))
(defun gzip-contents (pathname)
(with-open-file (stream pathname :direction :input
:element-type '(unsigned-byte 8))
(chipz:decompress nil 'chipz:zlib stream)))
(defun get-obj-type (pathname)
(with-open-file (stream pathname :direction :input
:element-type '(unsigned-byte 8))
(let ((result (chipz:decompress nil 'chipz:zlib stream)))
(octets-to-string (subseq result 0 (position 32 result))))))
(defun %parse-commit (contents result)
(let ((end-of-line (position 10 contents)))
(cond
((zerop end-of-line) (cons (octets-to-string (subseq contents 1))
result))
(t (%parse-commit
(subseq contents (1+ end-of-line))
(cons (octets-to-string (subseq contents 0 end-of-line)) result))))))
(defun parse-commit (contents)
(destructuring-bind (commit-message committer author parent tree)
(%parse-commit contents nil)
(make-instance 'commit
:tree (from-first-space tree)
:parent (from-first-space parent)
:author (from-first-space author)
:committer (from-first-space committer)
:commit-message (string-right-trim '(#\Newline) commit-message))))
(defclass tree-row ()
((filename :initarg :filename :reader filename)
(mode :initarg :mode :reader mode)
(sha1 :initarg :sha1 :reader sha1)))
(defun parse-tree (contents)
(let ((results nil)
(null-marker nil))
(tagbody
start
(setf null-marker (position 0 contents))
(unless null-marker
(go exit))
do
(let* ((before-null-marker (subseq contents 0 null-marker))
(space-marker (position 32 before-null-marker))
(sha1 (subseq contents
(1+ null-marker)
(+ 21 null-marker))))
(setf results (cons
(make-instance 'tree-row
:filename (subseq before-null-marker
(1+ space-marker))
:mode (subseq before-null-marker 0
space-marker)
:sha1 sha1)
results))
(setf contents (subseq contents (+ 21 null-marker))))
(go start)
exit)
results))
(defun parse-object (pathname)
(with-open-file (stream pathname :direction :input
:element-type '(unsigned-byte 8))
(let* ((result (chipz:decompress nil 'chipz:zlib stream))
(null-byte (position 0 result))
(header (subseq result 0 null-byte))
(delimiting-space (position 32 header))
(obj-type (octets-to-string (subseq header 0 delimiting-space)))
(obj-size (octets-to-string (subseq header (1+ delimiting-space))))
(obj-content (subseq result (1+ null-byte))))
(cond
((string= "blob" obj-type) (make-instance 'blob
:content obj-content
:size obj-size))
((string= "commit" obj-type) (parse-commit obj-content))
(t (values obj-type obj-size obj-content))))))
(defun return-last-commit (repo-pathname)
(with-open-file (in (format nil "~A.git/refs/heads/master" repo-pathname))
(let ((result (read-line in)))
(concatenate 'string
(format nil "~A.git/objects/" repo-pathname)
(subseq result 0 2)
"/"
(subseq result 2)))))
(return-last-commit "/home/puercopop/quicklisp/local-projects/nclack/")
#+nil(parse-object "/home/puercopop/quicklisp/local-projects/nclack/.git/objects/f8/08d0a8cc4a6d9a9ac434344e1daac69b320c48") ;; BLOB
#+nil(parse-object "/home/puercopop/quicklisp/local-projects/nclack/.git/objects/0d/4da89a1508b756a043a24e88741d5c4246a07e") ;; Commit
#+nil(parse-object "/home/puercopop/quicklisp/local-projects/nclack/.git/objects/13/cd2bb03b93f32b74a3b6e4bd23c4a5c044255f") ;; Tree
#+nil(get-obj-type
(with-open-file (in "/home/puercopop/quicklisp/local-projects/nclack/.git/refs/heads/master")
(let ((result (read-line in)))
(concatenate 'string
"/home/puercopop/quicklisp/local-projects/nclack/.git/objects/"
(subseq result 0 2)
"/"
(subseq result 2)))))
#+nil(uiop:directory-files "/home/puercopop/Projects/C-Data-Structures/.git/objects")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment