git.fiddlerwoaroof.com
Browse code

Handle :tree and :blob objects

Ed Langley authored on 07/05/2019 07:13:25
Showing 6 changed files
... ...
@@ -42,18 +42,55 @@
42 42
         (return-from find-object-in-pack-files
43 43
           (values pack mid))))))
44 44
 
45
-(defgeneric extract-object-of-type (type s)
46
-  (:method ((type integer) s)
45
+(defun behead (data)
46
+  (elt (partition 0 data)
47
+       1))
48
+
49
+(defun tree-entry (data)
50
+  (values-list (partition 0 data :with-offset 20)))
51
+
52
+(defun format-tree-entry (entry)
53
+  (destructuring-bind (info sha) (partition 0 entry)
54
+    (concatenate 'vector
55
+                 (apply #'concatenate 'vector
56
+                        (serapeum:intersperse (vector (char-code #\tab))
57
+                                              (reverse
58
+                                               (partition (char-code #\space)
59
+                                                          info))))
60
+                 (list (char-code #\tab))
61
+                 (babel:string-to-octets (elt (->sha-string sha) 0) :encoding *git-encoding*))))
62
+
63
+(defun tree-entries (data &optional accum)
64
+  (if (<= (length data) 0)
65
+      (apply #'concatenate 'vector
66
+             (serapeum:intersperse (vector (char-code #\newline))
67
+                                   (nreverse accum)))
68
+      (multiple-value-bind (next rest) (tree-entry data) 
69
+        (tree-entries rest
70
+                      (list* (format-tree-entry next)
71
+                             accum)))))
72
+
73
+(defgeneric extract-object-of-type (type s repository)
74
+  (:method ((type integer) s repository)
47 75
     (extract-object-of-type (object-type->sym type)
48
-                            s))
49
-  (:method ((type (eql :commit)) (s stream))
50
-    (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) s)))
76
+                            s
77
+                            repository))
78
+
79
+  (:method ((type (eql :commit)) (s stream) repository)
80
+    (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) s))
81
+
82
+  (:method ((type (eql :blob)) (s stream) repository)
83
+    (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) s))
84
+
85
+  (:method ((type (eql :tree)) (s stream) repository)
86
+    (let* ((data (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) s)))
87
+      (tree-entries data))))
51 88
 
52
-(defun read-object-from-pack (s)
89
+(defun read-object-from-pack (s repository)
53 90
   (let* ((metadata (fwoar.bin-parser:extract-high s))
54 91
          (type (get-object-type metadata))
55 92
          (size (get-object-size metadata))
56
-         (object-data (extract-object-of-type type s)))
93
+         (object-data (extract-object-of-type type s repository)))
57 94
     (list (cons :type (object-type->sym type))
58 95
           (cons :decompressed-size size)
59 96
           (cons :object-data object-data)
... ...
@@ -67,7 +104,7 @@
67 104
         (file-position s (+ offset-offset (* 4 obj-number)))
68 105
         (let ((object-offset-in-pack (read-bytes 4 'fwoar.bin-parser:be->int s)))
69 106
           (file-position p object-offset-in-pack)
70
-          (read-object-from-pack p))))))
107
+          (read-object-from-pack p (repository pack)))))))
71 108
 
72 109
 (defun extract-loose-object (repo id)
73 110
   (with-open-file (s (object repo id)
... ...
@@ -21,6 +21,8 @@
21 21
   (fw.lu:new 'git-graph repo))
22 22
 
23 23
 (defun get-commit-parents (repository commit)
24
+  #+lispworks
25
+  (declare (notinline mismatch serapeum:string-prefix-p))
24 26
   (map 'list 
25 27
        (serapeum:op (second (partition #\space _)))
26 28
        (remove-if-not (lambda (it)
... ...
@@ -5,7 +5,8 @@
5 5
 
6 6
 (defclass pack ()
7 7
   ((%pack :initarg :pack :reader pack-file)
8
-   (%index :initarg :index :reader index-file)))
8
+   (%index :initarg :index :reader index-file)
9
+   (%repository :initarg :repository :reader repository)))
9 10
 
10 11
 (defclass repository ()
11 12
   ((%root :initarg :root :reader root)))
... ...
@@ -25,8 +26,11 @@
25 26
     (6 :ofs-delta)
26 27
     (7 :ref-delta)))
27 28
 
28
-(defun repository (root)
29
-  (fw.lu:new 'repository root))
29
+(defgeneric repository (root)
30
+  (:method ((root string))
31
+   (fw.lu:new 'repository root))
32
+  (:method ((root pathname))
33
+   (fw.lu:new 'repository root)))
30 34
 
31 35
 (defun get-local-branches (root)
32 36
   (append (get-local-unpacked-branches root)
... ...
@@ -36,11 +40,12 @@
36 40
   (let ((obj-path (fwoar.string-utils:insert-at 2 #\/ sha)))
37 41
     (merge-pathnames obj-path ".git/objects/")))
38 42
 
39
-(defun pack (index pack)
40
-  (fw.lu:new 'pack index pack))
43
+(defun pack (index pack repository)
44
+  (fw.lu:new 'pack index pack repository))
41 45
 
42 46
 (defun pack-files (repo)
43
-  (mapcar 'pack
47
+  (mapcar (serapeum:op
48
+            (pack _ _ (repository repo)))
44 49
           (uiop:directory*
45 50
            (merge-pathnames ".git/objects/pack/*.idx"
46 51
                             repo))
... ...
@@ -10,4 +10,4 @@
10 10
 (defpackage :git
11 11
   (:use)
12 12
   (:export #:show #:branch #:branches #:commit-parents #:in-repository
13
-           #:current-repository #:show-repository))
13
+           #:current-repository #:show-repository #:git))
... ...
@@ -12,13 +12,34 @@
12 12
 (defun git:show-repository ()
13 13
   *git-repository*)
14 14
 
15
+(defmacro git:git (&rest commands)
16
+  `(uiop:nest ,@(reverse
17
+                 (mapcar (serapeum:op (case (car _1)
18
+                                        ((<<=) (list* 'mapcan
19
+                                                      (list 'quote
20
+                                                            (intern (symbol-name (cadadr _1))
21
+                                                                    :git))
22
+                                                      (cddr _1)))
23
+                                        ((map) (list* 'mapcar
24
+                                                      (list 'quote
25
+                                                            (intern (symbol-name (cadadr _1))
26
+                                                                    :git))
27
+                                                      (cddr _1)))
28
+                                        (t (cons (intern (symbol-name (car _1))
29
+                                                         :git)
30
+                                                 (cdr _1)))))
31
+                         commands))))
32
+
15 33
 (defun git:show (object)
16 34
   (babel:octets-to-string
17
-   (extract-object (repository *git-repository*)
18
-                   object)
35
+   (coerce (extract-object (repository *git-repository*)
36
+                           object)
37
+           '(vector serapeum:octet))
19 38
    :encoding *git-encoding*))
20 39
 
21 40
 (defun git:branch (&optional (branch "master"))
41
+  #+lispworks
42
+  (declare (notinline serapeum:assocadr))
22 43
   (let ((branches (branches (repository *git-repository*))))
23 44
     (nth-value 0 (serapeum:assocadr branch branches
24 45
                                     :test 'equal))))
... ...
@@ -28,11 +28,14 @@
28 28
     (inspect- *trace-output*
29 29
               (apply fn args))))
30 30
 
31
-(defun partition (char string &key from-end)
31
+(defun partition (char string &key from-end (with-offset nil wo-p))
32 32
   (let ((pos (position char string :from-end from-end)))
33 33
     (if pos
34
-        (list (subseq string 0 pos)
35
-              (subseq string (1+ pos)))
34
+        (if wo-p 
35
+            (list (subseq string 0 (+ pos with-offset 1))
36
+                  (subseq string (+ pos 1 with-offset)))
37
+            (list (subseq string 0 pos)
38
+                  (subseq string (1+ pos))))
36 39
       (list string
37 40
             nil))))
38 41