git.fiddlerwoaroof.com
Raw Blame History
(in-package :fwoar.cl-git)

(defmacro defclass+ (name (&rest super) &body (direct-slots &rest options))
  (let ((initargs (mapcan (lambda (slot)
                            (serapeum:unsplice
                             (make-symbol
                              (symbol-name
                               (getf (cdr slot)
                                     :initarg)))))
                          direct-slots)))
    `(progn (defclass ,name ,super
              ,direct-slots
              ,@options)
            (defun ,name (,@initargs)
              (fw.lu:new ',name ,@initargs)))))

(defclass delta ()
  ((%repository :initarg :repository :reader repository)
   (%base :initarg :base :reader base)
   (%commands :initarg :commands :reader commands)))

(defclass+ ofs-delta (delta)
  ())

(defclass+ ref-delta (delta)
  ())

(defun make-ofs-delta (base commands repository)
  (fw.lu:new 'ofs-delta base commands repository))
(defun make-ref-delta (base commands repository)
  (fw.lu:new 'ofs-delta base commands repository))

(defun int->bit-vector (n)
  (let* ((integer-length (integer-length n))
         (bv-size (* 8 (ceiling integer-length 8)))
         (bv (make-array bv-size :element-type 'bit)))
    (loop :for ix :below integer-length
          :do (setf (aref bv (- bv-size 1 ix))
                    (if (logbitp ix n)
                        1
                        0)))
    bv))

(defun bit-vector->int (bv)
  (let ((bv-size (array-total-size bv)))
    (loop :for ix :from (1- bv-size) :downto 0
          :for n :from 0
          :unless (zerop (aref bv ix))
            :sum (expt 2 n))))

(defun partition-commands (data)
  (let ((idx 0))
    (labels ((advance ()
               (prog1 (elt data idx)
                 (incf idx)))
             (get-command ()
               (let* ((bv (int->bit-vector (elt data idx)))
                      (discriminator (elt bv 0))
                      (insts (subseq bv 1)))
                 (incf idx)
                 (if (= 1 discriminator)
                     (list :copy
                           insts
                           (coerce (loop repeat (count 1 insts) collect (advance))
                                   '(vector (unsigned-byte 8))))
                     (list :add
                           (coerce (loop repeat (1- (bit-vector->int (reverse insts)))
                                         collect (advance))
                                   '(vector (unsigned-byte 8))))))))
      (loop while (< idx (length data))
            collect (get-command)))))

(defmethod -extract-object-of-type ((type (eql :ofs-delta)) s repository &key offset-from)
  (format t "~&data: ~s~%" s)
  (make-ofs-delta offset-from
                  (partition-commands s)
                  repository))
(defmethod -extract-object-of-type ((type (eql :ref-delta)) s repository &key offset-from)
  (make-ref-delta offset-from
                  (partition-commands s)
                  repository))


#+(or) #+(or) #+(or)

(defmethod component ((component (eql :tree)) (object git-commit))
  (ensure-ref
   (cadr
    (fw.lu:v-assoc :tree (metadata object)
                   :test 'string-equal))))
(defmethod component ((component (eql :parents)) (object git-commit))
  (coerce (remove-if-not (serapeum:op
                           (string= "parent" _))
                         (metadata object)
                         :key #'car)
          'list))
(defmethod component ((component (eql :message)) (object git-commit))
  (data object))