Browse code
Update git code to handle packed refs
Ed Langley authored on 06/05/2019 05:52:41
Showing 3 changed files
Showing 3 changed files
... | ... |
@@ -68,8 +68,9 @@ |
68 | 68 |
(defun extract-loose-object (repo id) |
69 | 69 |
(with-open-file (s (object repo id) |
70 | 70 |
:element-type '(unsigned-byte 8)) |
71 |
- (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) |
|
72 |
- s))) |
|
71 |
+ (alexandria:when-let ((result (chipz:decompress nil (chipz:make-dstate 'chipz:zlib) |
|
72 |
+ s))) |
|
73 |
+ (babel:octets-to-string result)))) |
|
73 | 74 |
|
74 | 75 |
(defun extract-object (repo id) |
75 | 76 |
(if (object repo id) |
76 | 77 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,73 @@ |
1 |
+(in-package :fwoar.cl-git) |
|
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 |
+ |
|
10 |
+(defclass repository () |
|
11 |
+ ((%root :initarg :root :reader root))) |
|
12 |
+ |
|
13 |
+(defclass git-object () |
|
14 |
+ ()) |
|
15 |
+ |
|
16 |
+(defclass commit (git-object) |
|
17 |
+ ()) |
|
18 |
+ |
|
19 |
+(defun object-type->sym (object-type) |
|
20 |
+ (ecase object-type |
|
21 |
+ (1 :commit) |
|
22 |
+ (2 :tree) |
|
23 |
+ (3 :blob) |
|
24 |
+ (4 :tag) |
|
25 |
+ (6 :ofs-delta) |
|
26 |
+ (7 :ref-delta))) |
|
27 |
+ |
|
28 |
+(defun repository (root) |
|
29 |
+ (fw.lu:new 'repository root)) |
|
30 |
+ |
|
31 |
+(defun get-local-unpacked-branches (root) |
|
32 |
+ (mapcar (data-lens:juxt #'pathname-name |
|
33 |
+ (alexandria:compose #'serapeum:trim-whitespace |
|
34 |
+ #'alexandria:read-file-into-string)) |
|
35 |
+ (uiop:directory* |
|
36 |
+ (merge-pathnames ".git/refs/heads/*" |
|
37 |
+ root)))) |
|
38 |
+ |
|
39 |
+(defun get-local-packed-branches (root) |
|
40 |
+ (let* ((packed-ref-file-name (merge-pathnames ".git/packed-refs" |
|
41 |
+ root))) |
|
42 |
+ (when (probe-file packed-ref-file-name) |
|
43 |
+ (with-open-file (s packed-ref-file-name) |
|
44 |
+ (loop for line = (read-line s nil) |
|
45 |
+ for parts = (partition #\space line) |
|
46 |
+ for branch-name = (second parts) |
|
47 |
+ while line |
|
48 |
+ unless (alexandria:starts-with-subseq "#" line) |
|
49 |
+ when (alexandria:starts-with-subseq "refs/heads" branch-name) |
|
50 |
+ collect (list (subseq branch-name |
|
51 |
+ (1+ (position #\/ branch-name |
|
52 |
+ :from-end t))) |
|
53 |
+ (first parts))))))) |
|
54 |
+ |
|
55 |
+(defun get-local-branches (root) |
|
56 |
+ (append (get-local-unpacked-branches root) |
|
57 |
+ (get-local-packed-branches root))) |
|
58 |
+ |
|
59 |
+(defun loose-object-path (sha) |
|
60 |
+ (let ((obj-path (fwoar.string-utils:insert-at 2 #\/ sha))) |
|
61 |
+ (merge-pathnames obj-path ".git/objects/"))) |
|
62 |
+ |
|
63 |
+(defun pack (index pack) |
|
64 |
+ (fw.lu:new 'pack index pack)) |
|
65 |
+ |
|
66 |
+(defun pack-files (repo) |
|
67 |
+ (mapcar 'pack |
|
68 |
+ (uiop:directory* |
|
69 |
+ (merge-pathnames ".git/objects/pack/*.idx" |
|
70 |
+ repo)) |
|
71 |
+ (uiop:directory* |
|
72 |
+ (merge-pathnames ".git/objects/pack/*.pack" |
|
73 |
+ repo)))) |
... | ... |
@@ -31,25 +31,25 @@ |
31 | 31 |
(defun partition (char string &key from-end) |
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))) |
|
36 |
- (list string |
|
37 |
- nil)))) |
|
34 |
+ (list (subseq string 0 pos) |
|
35 |
+ (subseq string (1+ pos))) |
|
36 |
+ (list string |
|
37 |
+ nil)))) |
|
38 | 38 |
|
39 | 39 |
(defun partition-subseq (subseq string &key from-end) |
40 | 40 |
(let ((pos (search subseq string :from-end from-end))) |
41 | 41 |
(if pos |
42 |
- (list (subseq string 0 pos) |
|
43 |
- (subseq string (+ (length subseq) pos))) |
|
44 |
- (list string |
|
45 |
- nil)))) |
|
42 |
+ (list (subseq string 0 pos) |
|
43 |
+ (subseq string (+ (length subseq) pos))) |
|
44 |
+ (list string |
|
45 |
+ nil)))) |
|
46 | 46 |
|
47 | 47 |
(serapeum:defalias ->sha-string |
48 | 48 |
(data-lens:<>1 (data-lens:over 'fwoar.bin-parser:byte-array-to-hex-string) |
49 | 49 |
'batch-20)) |
50 | 50 |
|
51 | 51 |
(defun read-bytes (count format stream) |
52 |
- (let ((seq (make-array count))) |
|
52 |
+ (let ((seq (make-array count :element-type 'serapeum:octet))) |
|
53 | 53 |
(read-sequence seq stream) |
54 | 54 |
(funcall format |
55 | 55 |
seq))) |
... | ... |
@@ -74,4 +74,5 @@ |
74 | 74 |
(partition-subseq #(#\newline #\newline) |
75 | 75 |
commit #+(or)(babel:octets-to-string commit :encoding :latin1)) |
76 | 76 |
(values message |
77 |
- (fwoar.string-utils:split #\newline metadata)))) |
|
77 |
+ (map 'vector (serapeum:op (partition #\space _)) |
|
78 |
+ (fwoar.string-utils:split #\newline metadata))))) |