git.fiddlerwoaroof.com
Browse code

feat: finish delta decoding

Edward Langley authored on 26/10/2023 00:46:12
Showing 1 changed files
... ...
@@ -3,7 +3,9 @@
3 3
 (defclass delta (git-object)
4 4
   ((%repository :initarg :repository :reader repository)
5 5
    (%base :initarg :base :reader base)
6
-   (%commands :initarg :commands :reader commands)))
6
+   (%commands :initarg :commands :reader commands)
7
+   (%src-size :initarg :src-size :reader src-size)
8
+   (%delta-size :initarg :delta-size :reader delta-size)))
7 9
 
8 10
 (defclass+ ofs-delta (delta)
9 11
   ())
... ...
@@ -11,8 +13,8 @@
11 13
 (defclass+ ref-delta (delta)
12 14
   ())
13 15
 
14
-(defun make-ofs-delta (base commands repository)
15
-  (fw.lu:new 'ofs-delta base commands repository))
16
+(defun make-ofs-delta (base commands repository src-size delta-size)
17
+  (fw.lu:new 'ofs-delta base commands repository src-size delta-size))
16 18
 (defun make-ref-delta (base commands repository)
17 19
   (fw.lu:new 'ofs-delta base commands repository))
18 20
 
... ...
@@ -35,8 +37,18 @@
35 37
             :sum (expt 2 n))))
36 38
 
37 39
 (defun expand-copy (copy)
38
-  ;; TODO: implement this
39
-  copy)
40
+  (destructuring-bind (command layout numbers) copy
41
+    (let* ((next-idx 0)
42
+           (parts (map '(vector (unsigned-byte 8))
43
+                       (lambda (layout-bit)
44
+                         (if (= layout-bit 1)
45
+                             (prog1 (elt numbers next-idx)
46
+                               (incf next-idx))
47
+                             0))
48
+                       (reverse layout))))
49
+      (list command
50
+            (fwoar.bin-parser:le->int (subseq parts 0 4))
51
+            (fwoar.bin-parser:le->int (subseq parts 4))))))
40 52
 
41 53
 (defun partition-commands (data)
42 54
   (let ((idx 0))
... ...
@@ -70,45 +82,47 @@
70 82
     (flet ((advance ()
71 83
              (prog1 (elt buf idx)
72 84
                (incf idx))))
73
-      (let* ((c (advance))
74
-             (ofs (logand c 127)))
75
-        (loop
76
-          do (format t "~&~s ~s ~s" idx c ofs)
77
-          while (> (logand c 128) 0)
78
-          do
79
-             (setf c (advance))
80
-             (setf ofs (+ (ash (1+ ofs)
81
-                               7)
82
-                          (logand c 127))))
83
-        (values (- ofs) idx)))))
85
+      (loop for c = (advance)
86
+            for ofs = (logand c 127)
87
+            for morep = (> (logand c 128) 0)
88
+            while morep
89
+            finally
90
+               (return (values (- ofs) idx))))))
91
+
92
+(defun decode-size (buf)
93
+  (let ((parts ()))
94
+    (loop for raw across buf
95
+          for bits = (int->bit-vector raw)
96
+          for morep = (= (elt bits 0) 1)
97
+          do (push (subseq bits 1) parts)
98
+          while morep)
99
+    (let ((result (make-array (* 7 (length parts))
100
+                              :element-type 'bit)))
101
+      (loop for x from 0 by 7
102
+            for part in parts
103
+            do
104
+               (replace result part :start1 x))
105
+      (values (bit-vector->int result)
106
+              (length parts)))))
84 107
 
85 108
 (defmethod -extract-object-of-type ((type (eql :ofs-delta)) s repository &key offset-from packfile)
86 109
   (multiple-value-bind (offset consumed) (get-ofs-delta-offset s)
87
-    (make-ofs-delta (list packfile
88
-                          (+ offset-from offset))
89
-                    (partition-commands (chipz:decompress
90
-                                         nil
91
-                                         (chipz:make-dstate 'chipz:zlib)
92
-                                         (subseq s consumed)))
93
-                    repository)))
110
+    (let ((compressed-data (chipz:decompress
111
+                            nil
112
+                            (chipz:make-dstate 'chipz:zlib)
113
+                            (subseq s consumed))))
114
+      (multiple-value-bind (src-size consumed-1) (decode-size compressed-data)
115
+        (multiple-value-bind (delta-size consumed-2) (decode-size (subseq compressed-data
116
+                                                                          consumed-1))
117
+          (make-ofs-delta (list packfile
118
+                                (+ offset-from offset))
119
+                          (partition-commands (subseq compressed-data
120
+                                                      (+ consumed-1
121
+                                                         consumed-2)))
122
+                          repository
123
+                          src-size
124
+                          delta-size))))))
94 125
 (defmethod -extract-object-of-type ((type (eql :ref-delta)) s repository &key offset-from)
95 126
   (make-ref-delta offset-from
96 127
                   (partition-commands s)
97 128
                   repository))
98
-
99
-
100
-#+(or) #+(or) #+(or)
101
-
102
-(defmethod component ((component (eql :tree)) (object git-commit))
103
-  (ensure-ref
104
-   (cadr
105
-    (fw.lu:v-assoc :tree (metadata object)
106
-                   :test 'string-equal))))
107
-(defmethod component ((component (eql :parents)) (object git-commit))
108
-  (coerce (remove-if-not (serapeum:op
109
-                           (string= "parent" _))
110
-                         (metadata object)
111
-                         :key #'car)
112
-          'list))
113
-(defmethod component ((component (eql :message)) (object git-commit))
114
-  (data object))