-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathng-indexes.lisp
143 lines (125 loc) · 4.79 KB
/
ng-indexes.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
;;;; ng-indexes.lisp
(in-package #:quicklisp-controller)
(defclass controller-dist-object ()
((name
:initarg :name
:reader name)))
(defclass controller-dist (controller-dist-object)
((provided-releases
:initarg :provided-releases
:initform nil
:accessor provided-releases)
(system-table
:initarg :system-table
:initform (make-string-table)
:reader system-table)
(release-table
:initarg :release-table
:initform (make-string-table)
:reader release-table))
(:default-initargs
:name "quicklisp-controller"))
(defclass controller-release (controller-dist-object)
((source
:initarg :source
:reader source)
(provided-systems
:initarg :provided-systems
:accessor provided-systems)
(dist
:initarg :dist
:accessor dist)))
(defmethod print-object ((object controller-dist-object) stream)
(print-unreadable-object (object stream :type t)
(format stream "~S" (name object))))
(defclass controller-system (controller-dist-object)
((system-file-name
:initarg :system-file-name
:reader system-file-name)
(required-systems
:initarg :required-systems
:reader required-systems)
(release
:initarg :release
:accessor release)))
(defmethod name ((source upstream-source))
(project-name source))
(defun make-controller-system (winner-info &key release)
(destructuring-bind (system-file-name system-name
&rest required-system-names)
winner-info
(make-instance 'controller-system
:release release
:name system-name
:system-file-name system-file-name
:required-systems required-system-names)))
(defun make-controller-dist ()
(let ((dist (make-instance 'controller-dist)))
(map-sources
(lambda (source)
(let ((winners (find-winning-systems source)))
(when winners
(let* ((release (make-instance 'controller-release
:source source
:name (project-name source)
:dist dist))
(systems (mapcar 'make-controller-system winners)))
(setf (dist release) dist)
(setf (provided-systems release) systems)
(dolist (system systems)
(setf (release system) release)
(setf (gethash (name system) (system-table dist)) system))
(setf (gethash (name release) (release-table dist)) release)
(push release (provided-releases dist)))))))
dist))
(defun slashed-name-p (name)
(position #\/ name))
(defun flat-unique (strings &key (test 'equalp))
(remove-duplicates (alexandria:flatten strings) :test test))
(defun resolve-slashed-system (system-name required-system-name dist)
(let ((system-table (system-table dist)))
(labels ((lookup (name)
(or (gethash name system-table)
(progn (warn "Unknown system ~S" name)
nil)))
(maybe-required-systems (thing)
(when thing
(required-systems thing)))
(resolve (name)
(let* ((unslashed (unslashify-system-name name))
(slashedp (slashed-name-p name))
(samep (and slashedp (equal system-name unslashed))))
(cond ((and slashedp samep)
(flat-unique
(mapcar #'resolve
(maybe-required-systems (lookup name)))))
(slashedp
unslashed)
(t
name)))))
(resolve required-system-name))))
(defmethod dist ((system controller-system))
(dist (release system)))
(defun resolved-required-systems (system)
(let ((dist (dist system))
(name (name system)))
(flat-unique
(mapcar (lambda (required-system-name)
(resolve-slashed-system name required-system-name dist))
(required-systems system)))))
(defmethod provided-systems ((dist controller-dist))
(loop for release in (provided-releases dist)
appending (provided-systems release)))
(defun write-systems-index (dist file)
(let ((systems (provided-systems dist)))
(setf systems (sort (copy-list systems) #'string< :key 'name))
(with-open-file (stream file :direction :output
:if-exists :supersede)
(write-line *system-file-header* stream)
(dolist (system systems)
(unless (slashed-name-p (name system))
(format stream "~A ~A ~A~{ ~A~}~%"
(name (release system))
(system-file-name system)
(name system)
(resolved-required-systems system)))))))