Last active
August 29, 2015 14:13
-
-
Save PuercoPop/a5f36d42dd2a7997b2a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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