git.fiddlerwoaroof.com
Browse code

Split files

Ed Langley authored on 03/05/2019 06:36:47
Showing 6 changed files
... ...
@@ -7,12 +7,16 @@
7 7
   :license "MIT"
8 8
   :pathname #-fw.dev nil #+fw.dev #p"PROJECTS:cl-git;"
9 9
   :depends-on (:alexandria
10
-               :split-sequence
11
-               :cl-dot
12 10
                :chipz
11
+               :cl-dot
13 12
                :data-lens
14 13
                :fwoar-lisputils
15 14
                :fwoar-lisputils/bin-parser
15
+               :ironclad
16 16
                :serapeum
17
+               :split-sequence
17 18
                :uiop)
18
-  :components ((:file "cl-git")))
19
+  :components ((:file "package")
20
+               (:file "util" :depends-on ("package"))
21
+               (:file "git" :depends-on ("package" "util"))
22
+               (:file "porcelain" :depends-on ("package" "git"))))
19 23
similarity index 67%
20 24
rename from cl-git.lisp
21 25
rename to git.lisp
... ...
@@ -1,11 +1,21 @@
1
-(defpackage :fwoar.cl-git
2
-  (:use :cl )
3
-  (:export ))
4 1
 (in-package :fwoar.cl-git)
5 2
 
3
+(defparameter *object-data-lens*
4
+  (data-lens.lenses:make-alist-lens :object-data))
5
+
6
+(defclass pack ()
7
+  ((%pack :initarg :pack :reader pack-file)
8
+   (%index :initarg :index :reader index-file)))
9
+
6 10
 (defclass repository ()
7 11
   ((%root :initarg :root :reader root)))
8 12
 
13
+(defclass git-object ()
14
+  ())
15
+
16
+(defclass commit (git-object)
17
+  ())
18
+
9 19
 (defun repository (root)
10 20
   (fw.lu:new 'repository root))
11 21
 
... ...
@@ -21,10 +31,6 @@
21 31
   (let ((obj-path (fwoar.string-utils:insert-at 2 #\/ sha)))
22 32
     (merge-pathnames obj-path ".git/objects/")))
23 33
 
24
-(defclass pack ()
25
-  ((%pack :initarg :pack :reader pack-file)
26
-   (%index :initarg :index :reader index-file)))
27
-
28 34
 (defun pack (index pack)
29 35
   (fw.lu:new 'pack index pack))
30 36
 
... ...
@@ -47,9 +53,10 @@
47 53
 (defun edges-in-fanout (toc s sha)
48 54
   (let* ((fanout-offset (getf toc :fanout)))
49 55
     (file-position s (+ fanout-offset (* 4 (1- (elt sha 0)))))
50
-    (destructuring-bind ((_ . cur) (__ . next)) (fwoar.bin-parser:extract '((cur 4 fwoar.bin-parser:be->int)
51
-                                                                            (next 4 fwoar.bin-parser:be->int))
52
-                                                                          s)
56
+    (destructuring-bind ((_ . cur) (__ . next))
57
+        (fwoar.bin-parser:extract '((cur 4 fwoar.bin-parser:be->int)
58
+                                    (next 4 fwoar.bin-parser:be->int))
59
+                                  s)
53 60
       (declare (ignore _ __))
54 61
       (values cur next))))
55 62
 
... ...
@@ -67,7 +74,8 @@
67 74
               (t mid))))))
68 75
 
69 76
 (defun find-pack-containing (pack-file id)
70
-  (with-open-file (s (index-file pack-file) :element-type '(unsigned-byte 8))
77
+  (with-open-file (s (index-file pack-file)
78
+                     :element-type '(unsigned-byte 8))
71 79
     (let ((binary-sha (ironclad:hex-string-to-byte-array id))
72 80
           (toc (idx-toc s)))
73 81
       (multiple-value-bind (_ end) (edges-in-fanout toc s binary-sha)
... ...
@@ -87,6 +95,19 @@
87 95
           (file-position p object-offset-in-pack)
88 96
           (read-object-from-pack p))))))
89 97
 
98
+(defun seek-to-object-in-pack (idx-stream pack-stream obj-number)
99
+  (let* ((toc (idx-toc idx-stream))
100
+         (offset-offset (getf toc :4-byte-offsets)))
101
+    (file-position idx-stream (+ offset-offset (* 4 obj-number)))
102
+    (let ((object-offset-in-pack (read-bytes 4 'fwoar.bin-parser:be->int idx-stream)))
103
+      (file-position pack-stream object-offset-in-pack))))
104
+
105
+(defun extract-object-metadata-from-pack (pack obj-number)
106
+  (with-open-file (s (index-file pack) :element-type '(unsigned-byte 8))
107
+    (with-open-file (p (pack-file pack) :element-type '(unsigned-byte 8))
108
+      (seek-to-object-in-pack s p obj-number)
109
+      (read-object-metadata-from-pack p))))
110
+
90 111
 (defun extract-loose-object (repo id)
91 112
   (with-open-file (s (object repo id)
92 113
                      :element-type '(unsigned-byte 8))
... ...
@@ -100,8 +121,6 @@
100 121
                              (multiple-value-call 'extract-object-from-pack 
101 122
                                (find-object-in-pack-files (root repo) id)))))
102 123
 
103
-(defparameter *object-data-lens*
104
-  (data-lens.lenses:make-alist-lens :object-data))
105 124
 
106 125
 (defun turn-read-object-to-string (object)
107 126
   (data-lens.lenses:over *object-data-lens* 'babel:octets-to-string object))
... ...
@@ -133,13 +152,6 @@
133 152
            'fanout-table)
134 153
           'vector))
135 154
 
136
-(defun batch-4 (bytes)
137
-  (mapcar 'fwoar.bin-parser:be->int
138
-          (serapeum:batches bytes 4)))
139
-
140
-(defun batch-20 (bytes)
141
-  (serapeum:batches bytes 20))
142
-
143 155
 (defun get-object-size (bytes)
144 156
   (let ((first (elt bytes 0))
145 157
         (rest (subseq bytes 1)))
... ...
@@ -151,10 +163,6 @@
151 163
     (ldb (byte 3 4)
152 164
          first)))
153 165
 
154
-(serapeum:defalias ->sha-string
155
-  (<>1 (data-lens:over 'fwoar.bin-parser:byte-array-to-hex-string)
156
-       batch-20))
157
-
158 166
 (defun get-shas-before (fanout-table first-sha-byte s)
159 167
   (let ((num-before (elt fanout-table first-sha-byte))
160 168
         (num-total (alexandria:last-elt fanout-table)))
... ...
@@ -175,11 +183,6 @@
175 183
   (fwoar.bin-parser:extract '((offset 4 fwoar.bin-parser:be->int))
176 184
                             s))
177 185
 
178
-(defmacro sym->plist (&rest syms)
179
-  `(list ,@(loop for sym in syms
180
-                 append (list (alexandria:make-keyword sym)
181
-                              sym))))
182
-
183 186
 (defun idx-toc (idx-stream)
184 187
   (let* ((object-count (progn (file-position idx-stream 1028)
185 188
                               (let ((buf (make-array 4)))
... ...
@@ -224,6 +227,7 @@
224 227
         (crc-idx (getf idx-toc :packed-crcs))
225 228
         (4-byte-offsets-idx (getf idx-toc :4-byte-offsets))
226 229
         (8-byte-offsets-idx (getf idx-toc :8-byte-offsets)))
230
+    (declare (ignore 8-byte-offsets-idx))
227 231
     (values num
228 232
             (progn
229 233
               (file-position s (+ sha-idx (* num 20)))
... ...
@@ -275,38 +279,6 @@
275 279
               result))
276 280
       )))
277 281
 
278
-(defmacro inspect- (s form)
279
-  `(let ((result ,form))
280
-     (format ,s "~&~s (~{~s~^ ~})~%~4t~s~%"
281
-             ',form
282
-             ,(typecase form
283
-                (list `(list ',(car form) ,@(cdr form)))
284
-                (t `(list ,form)))
285
-             result)
286
-     result))
287
-
288
-(defun inspect-* (fn)
289
-  (lambda (&rest args)
290
-    (declare (dynamic-extent args))
291
-    (inspect- *trace-output*
292
-              (apply fn args))))
293
-
294
-(defun partition (char string &key from-end)
295
-  (let ((pos (position char string :from-end from-end)))
296
-    (if pos
297
-	      (list (subseq string 0 pos)
298
-	            (subseq string (1+ pos)))
299
-	      (list string
300
-	            nil))))
301
-
302
-(defun partition-subseq (subseq string &key from-end)
303
-  (let ((pos (search subseq string :from-end from-end)))
304
-    (if pos
305
-	      (list (subseq string 0 pos)
306
-	            (subseq string (+ (length subseq) pos)))
307
-	      (list string
308
-	            nil))))
309
-
310 282
 (defun split-object (object-data)
311 283
   (destructuring-bind (head tail)
312 284
       (partition 0
... ...
@@ -318,10 +290,6 @@
318 290
               (list type
319 291
                     (parse-integer length))))))
320 292
 
321
-(defclass git-object ()
322
-  ())
323
-(defclass commit (git-object)
324
-  ())
325 293
 
326 294
 (defun parse-commit (commit)
327 295
   (destructuring-bind (metadata message)
... ...
@@ -329,65 +297,3 @@
329 297
                         commit #+(or)(babel:octets-to-string commit :encoding :latin1))
330 298
     (values message
331 299
             (fwoar.string-utils:split #\newline metadata))))
332
-
333
-(defclass git-graph ()
334
-  ((%repo :initarg :repo :reader repo)
335
-   (%depth :initarg :depth :reader depth)
336
-   (%branches :reader branches)
337
-   (%node-cache :reader node-cache :initform (make-hash-table :test 'equal))
338
-   (%edge-cache :reader edge-cache :initform (make-hash-table :test 'equal))))
339
-
340
-(defmethod initialize-instance :after ((object git-graph) &key)
341
-  (setf (slot-value object '%branches)
342
-        (fw.lu:alist-string-hash-table
343
-         (funcall (data-lens:over
344
-                   (<>1 (data-lens:applying #'cons)
345
-                        (data-lens:transform-head
346
-                         (serapeum:op (subseq _1 0 (min (length _1) 7))))
347
-                        #'reverse))
348
-                  (branches (repo object))))))
349
-
350
-(defun git-graph (repo)
351
-  (fw.lu:new 'git-graph repo))
352
-
353
-(defun get-commit-parents (repository commit)
354
-  (map 'list 
355
-       (serapeum:op (second (partition #\space _)))
356
-       (remove-if-not (lambda (it)
357
-                        (serapeum:string-prefix-p "parent" it))
358
-                      (nth-value 1 (parse-commit
359
-                                    (split-object
360
-                                     (chipz:decompress nil (chipz:make-dstate 'chipz:zlib)
361
-                                                       (object repository
362
-                                                               commit))))))))
363
-
364
-(defmethod cl-dot:graph-object-node ((graph git-graph) (commit string))
365
-  (alexandria:ensure-gethash commit
366
-                             (node-cache graph)
367
-                             (make-instance 'cl-dot:node
368
-                                            :attributes `(:label ,(gethash #1=(subseq commit 0 7)
369
-                                                                           (branches graph)
370
-                                                                           #1#)))))
371
-
372
-(defmethod cl-dot:graph-object-points-to ((graph git-graph) (commit string))
373
-  (mapcar (lambda (c)
374
-            (setf (gethash (list commit c)
375
-                           (edge-cache graph))
376
-                  t)
377
-            c)
378
-          (remove-if (lambda (it)
379
-                       (gethash (list commit it)
380
-                                (edge-cache graph)))
381
-                     (mapcar (serapeum:op (subseq _ 0 7))
382
-                             (get-commit-parents (repo graph) commit)
383
-                             #+nil
384
-                             (loop
385
-                               for cur = (list commit) then parents
386
-                               for parents = (let ((f (get-commit-parents (repo graph) (car cur))))
387
-                                               f)
388
-                               until (or (not parents)
389
-                                         (cdr parents))
390
-                               finally (return (or parents
391
-                                                   (when (not (equal commit (car cur)))
392
-                                                     cur))))))))
393
-
394 300
new file mode 100644
... ...
@@ -0,0 +1,62 @@
1
+(in-package :fwoar.cl-git)
2
+
3
+(defclass git-graph ()
4
+  ((%repo :initarg :repo :reader repo)
5
+   (%depth :initarg :depth :reader depth)
6
+   (%branches :reader branches)
7
+   (%node-cache :reader node-cache :initform (make-hash-table :test 'equal))
8
+   (%edge-cache :reader edge-cache :initform (make-hash-table :test 'equal))))
9
+
10
+(defmethod initialize-instance :after ((object git-graph) &key)
11
+  (setf (slot-value object '%branches)
12
+        (fw.lu:alist-string-hash-table
13
+         (funcall (data-lens:over
14
+                   (<>1 (data-lens:applying #'cons)
15
+                        (data-lens:transform-head
16
+                         (serapeum:op (subseq _1 0 (min (length _1) 7))))
17
+                        #'reverse))
18
+                  (branches (repo object))))))
19
+
20
+(defun git-graph (repo)
21
+  (fw.lu:new 'git-graph repo))
22
+
23
+(defun get-commit-parents (repository commit)
24
+  (map 'list 
25
+       (serapeum:op (second (partition #\space _)))
26
+       (remove-if-not (lambda (it)
27
+                        (serapeum:string-prefix-p "parent" it))
28
+                      (nth-value 1 (parse-commit
29
+                                    (split-object
30
+                                     (chipz:decompress nil (chipz:make-dstate 'chipz:zlib)
31
+                                                       (object repository
32
+                                                               commit))))))))
33
+
34
+(defmethod cl-dot:graph-object-node ((graph git-graph) (commit string))
35
+  (alexandria:ensure-gethash commit
36
+                             (node-cache graph)
37
+                             (make-instance 'cl-dot:node
38
+                                            :attributes `(:label ,(gethash #1=(subseq commit 0 7)
39
+                                                                           (branches graph)
40
+                                                                           #1#)))))
41
+
42
+(defmethod cl-dot:graph-object-points-to ((graph git-graph) (commit string))
43
+  (mapcar (lambda (c)
44
+            (setf (gethash (list commit c)
45
+                           (edge-cache graph))
46
+                  t)
47
+            c)
48
+          (remove-if (lambda (it)
49
+                       (gethash (list commit it)
50
+                                (edge-cache graph)))
51
+                     (mapcar (serapeum:op (subseq _ 0 7))
52
+                             (get-commit-parents (repo graph) commit)
53
+                             #+nil
54
+                             (loop
55
+                               for cur = (list commit) then parents
56
+                               for parents = (let ((f (get-commit-parents (repo graph) (car cur))))
57
+                                               f)
58
+                               until (or (not parents)
59
+                                         (cdr parents))
60
+                               finally (return (or parents
61
+                                                   (when (not (equal commit (car cur)))
62
+                                                     cur))))))))
0 63
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+(in-package :cl-user)
2
+
3
+(defpackage :fwoar.cl-git
4
+  (:use :cl )
5
+  (:export ))
6
+
7
+(defpackage :cl-git-user
8
+  (:use :cl :fwoar.cl-git))
0 9
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+(in-package :fwoar.cl-git)
2
+
3
+(defvar *git-repository* nil
4
+  "The git repository path for porcelain commands to operate on.")
5
+(defvar *git-encoding* :utf-8
6
+  "The encoding to use when parsing git objects")
7
+
8
+(defun git-show (object)
9
+  (babel:octets-to-string (extract-object (repository *git-repository*)
10
+                                          object)
11
+                          :encoding *git-encoding*))
0 12
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+(in-package :fwoar.cl-git)
2
+
3
+(fw.lu:defun-ct batch-4 (bytes)
4
+  (mapcar 'fwoar.bin-parser:be->int
5
+          (serapeum:batches bytes 4)))
6
+
7
+(fw.lu:defun-ct batch-20 (bytes)
8
+  (serapeum:batches bytes 20))
9
+
10
+(defmacro sym->plist (&rest syms)
11
+  `(list ,@(loop for sym in syms
12
+                 append (list (alexandria:make-keyword sym)
13
+                              sym))))
14
+
15
+(defmacro inspect- (s form)
16
+  `(let ((result ,form))
17
+     (format ,s "~&~s (~{~s~^ ~})~%~4t~s~%"
18
+             ',form
19
+             ,(typecase form
20
+                (list `(list ',(car form) ,@(cdr form)))
21
+                (t `(list ,form)))
22
+             result)
23
+     result))
24
+
25
+(defun inspect-* (fn)
26
+  (lambda (&rest args)
27
+    (declare (dynamic-extent args))
28
+    (inspect- *trace-output*
29
+              (apply fn args))))
30
+
31
+(defun partition (char string &key from-end)
32
+  (let ((pos (position char string :from-end from-end)))
33
+    (if pos
34
+	      (list (subseq string 0 pos)
35
+	            (subseq string (1+ pos)))
36
+	      (list string
37
+	            nil))))
38
+
39
+(defun partition-subseq (subseq string &key from-end)
40
+  (let ((pos (search subseq string :from-end from-end)))
41
+    (if pos
42
+	      (list (subseq string 0 pos)
43
+	            (subseq string (+ (length subseq) pos)))
44
+	      (list string
45
+	            nil))))
46
+
47
+(serapeum:defalias ->sha-string
48
+  (data-lens:<>1 (data-lens:over 'fwoar.bin-parser:byte-array-to-hex-string)
49
+                 'batch-20))