Browse code
feat: add a git-repository class
Ed L authored on 15/11/2020 19:03:49
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -10,6 +10,8 @@ |
10 | 10 |
|
11 | 11 |
(defclass repository () |
12 | 12 |
((%root :initarg :root :reader root))) |
13 |
+(defclass git-repository (repository) |
|
14 |
+ ()) |
|
13 | 15 |
|
14 | 16 |
(defclass git-object () |
15 | 17 |
()) |
... | ... |
@@ -39,13 +41,51 @@ |
39 | 41 |
("ofs-delta" :ofs-delta) |
40 | 42 |
("ref-delta" :ref-delta))) |
41 | 43 |
|
42 |
-(defgeneric repository (root) |
|
44 |
+(define-condition alts-fallthrough (error) |
|
45 |
+ ((%fallthrough-message :initarg :fallthrough-message :reader fallthrough-message) |
|
46 |
+ (%args :initarg :args :reader args)) |
|
47 |
+ (:report (lambda (c s) |
|
48 |
+ (format s "~a ~s" |
|
49 |
+ (fallthrough-message c) |
|
50 |
+ (args c))))) |
|
51 |
+ |
|
52 |
+;; TODO: figure out how to handle ambiguity? restarts? |
|
53 |
+(define-method-combination alts (&key fallthrough-message) ((methods *)) |
|
54 |
+ (:arguments arg) |
|
55 |
+ (progn |
|
56 |
+ (mapc (serapeum:op |
|
57 |
+ (let ((qualifiers (method-qualifiers _1))) |
|
58 |
+ (unless (and (eql 'alts (car qualifiers)) |
|
59 |
+ (if (null (cdr qualifiers)) |
|
60 |
+ t |
|
61 |
+ (and (symbolp (cadr qualifiers)) |
|
62 |
+ (null (cddr qualifiers))))) |
|
63 |
+ (invalid-method-error _1 "invalid qualifiers: ~s" qualifiers)))) |
|
64 |
+ methods) |
|
65 |
+ `(or ,@(mapcar (serapeum:op `(call-method ,_1)) |
|
66 |
+ methods) |
|
67 |
+ (error 'alts-fallthrough |
|
68 |
+ :fallthrough-message ,fallthrough-message |
|
69 |
+ :args ,arg)))) |
|
70 |
+ |
|
71 |
+(defgeneric resolve-repository (object) |
|
72 |
+ (:documentation "resolve an OBJECT to a repository implementation") |
|
73 |
+ (:method-combination alts :fallthrough-message "failed to resolve repository")) |
|
74 |
+ |
|
75 |
+(defmethod resolve-repository alts :git ((root pathname)) |
|
76 |
+ (alexandria:when-let ((root (probe-file root))) |
|
77 |
+ (let* ((git-dir (merge-pathnames (make-pathname :directory '(:relative ".git")) |
|
78 |
+ root))) |
|
79 |
+ (when (probe-file git-dir) |
|
80 |
+ (fw.lu:new 'git-repository root))))) |
|
81 |
+ |
|
82 |
+(defgeneric repository (object) |
|
83 |
+ (:documentation "get the repository for an object") |
|
84 |
+ (:method ((root pathname)) |
|
85 |
+ (resolve-repository root)) |
|
43 | 86 |
(:method ((root string)) |
44 | 87 |
(let ((root (parse-namestring root))) |
45 |
- (repository root))) |
|
46 |
- (:method ((root pathname)) |
|
47 |
- (let ((root (truename root))) |
|
48 |
- (fw.lu:new 'repository root)))) |
|
88 |
+ (repository root)))) |
|
49 | 89 |
|
50 | 90 |
(defun get-local-branches (root) |
51 | 91 |
(append (get-local-unpacked-branches root) |