Browse code
Fix pathnames for sbcl
fiddlerwoaroof authored on 15/10/2016 09:58:45
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -9,6 +9,24 @@ |
9 | 9 |
(defparameter +dirname-format+ |
10 | 10 |
'((:year 4) #\- (:month 2) #\- (:day 2) #\/ (:hour 2) #\- (:min 2) #\/)) |
11 | 11 |
|
12 |
+(defmethod yason:encode ((object pathname) &optional stream) |
|
13 |
+ (yason:encode (princ-to-string (uiop:native-namestring object)) |
|
14 |
+ stream) |
|
15 |
+ object) |
|
16 |
+ |
|
17 |
+(defmethod yason:encode ((object puri:uri) &optional stream) |
|
18 |
+ (yason:encode (puri:render-uri object nil) |
|
19 |
+ stream) |
|
20 |
+ object) |
|
21 |
+ |
|
22 |
+(defun sha256-string (string) |
|
23 |
+ (let* ((digester (ironclad:make-digesting-stream :sha256)) |
|
24 |
+ (digest-stream (flexi-streams:make-flexi-stream digester))) |
|
25 |
+ (princ string digest-stream) |
|
26 |
+ (crypto:byte-array-to-hex-string |
|
27 |
+ (crypto:produce-digest |
|
28 |
+ digester)))) |
|
29 |
+ |
|
12 | 30 |
(defun get-store-directory-name (timestamp) |
13 | 31 |
(car |
14 | 32 |
(prog1-let ((result (merge-pathnames |
... | ... |
@@ -19,41 +37,86 @@ |
19 | 37 |
*feed-base*))) |
20 | 38 |
(ensure-directories-exist result)))) |
21 | 39 |
|
22 |
-(defmethod store ((feed alimenta:feed) directory) |
|
23 |
- (with-accessors ((description alimenta:description) |
|
24 |
- (feed-link alimenta:feed-link) |
|
25 |
- (items alimenta:items) |
|
26 |
- (link alimenta:link) |
|
27 |
- (source-type alimenta:source-type) |
|
28 |
- (title alimenta:title)) feed |
|
29 |
- (prog1-let ((feed-title title) |
|
30 |
- (feed-store (merge-pathnames (concatenate 'string (puri:uri-host feed-link) |
|
31 |
- "/") |
|
32 |
- directory))) |
|
33 |
- (ensure-directories-exist feed-store) |
|
34 |
- (with-open-file (index (merge-pathnames "index.json" feed-store) :direction :output) |
|
35 |
- (yason:with-output (index :indent t) |
|
36 |
- (yason:with-object () |
|
37 |
- (yason:encode-object-element "title" title) |
|
38 |
- (yason:encode-object-element "fetch-url" |
|
39 |
- (puri:render-uri feed-link nil)) |
|
40 |
- (yason:encode-object-element "link" link) |
|
41 |
- ;(yason:encode-object-element "source-type" source-type) |
|
42 |
- (yason:encode-object-element "description" description) |
|
43 |
- (yason:with-object-element ("items") |
|
44 |
- (yason:with-array () |
|
45 |
- (dolist (item (store items feed-store)) |
|
46 |
- (destructuring-bind (title path) item |
|
47 |
- (yason:with-object () |
|
48 |
- (yason:encode-object-element "title" title) |
|
49 |
- (yason:encode-object-element "path" path)))))))))))) |
|
40 |
+(defun fix-pathname () |
|
41 |
+ (let ((restart (find-restart 'fix-pathname))) |
|
42 |
+ (when restart |
|
43 |
+ (invoke-restart restart)))) |
|
44 |
+ |
|
45 |
+(defun encode-feed-as-json (feed item-storage-info root-dir &optional stream) |
|
46 |
+ (declare (optimize (debug 3))) |
|
47 |
+ (flet ((encode-item (item) |
|
48 |
+ (let ((restarted nil)) |
|
49 |
+ (destructuring-bind (title path) item |
|
50 |
+ (tagbody start |
|
51 |
+ (format t "~&Restarted: ~a" restarted) |
|
52 |
+ (when restarted |
|
53 |
+ (format t " ~a~%"(namestring path))) |
|
54 |
+ (restart-case |
|
55 |
+ (progn (format t "~&encoding . . .~%") |
|
56 |
+ (let ((pathname (uiop:enough-pathname path root-dir))) |
|
57 |
+ (yason:with-object () |
|
58 |
+ (yason:encode-object-element "title" title) |
|
59 |
+ (yason:encode-object-element "path" pathname)))) |
|
60 |
+ (fix-pathname () |
|
61 |
+ (setf path |
|
62 |
+ (merge-pathnames path |
|
63 |
+ (make-pathname :type :unspecific))) |
|
64 |
+ (unless restarted |
|
65 |
+ (setf restarted t) |
|
66 |
+ (go start))))))))) |
|
67 |
+ (with-accessors ((description alimenta:description) |
|
68 |
+ (feed-link alimenta:feed-link) |
|
69 |
+ (items alimenta:items) |
|
70 |
+ (link alimenta:link) |
|
71 |
+ (source-type alimenta:source-type) |
|
72 |
+ (title alimenta:title)) feed |
|
73 |
+ (yason:with-output (stream :indent t) |
|
74 |
+ (yason:with-object () |
|
75 |
+ (yason:encode-object-element "title" title) |
|
76 |
+ (yason:encode-object-element "fetch-url" |
|
77 |
+ (puri:render-uri feed-link nil)) |
|
78 |
+ (yason:encode-object-element "link" link) |
|
79 |
+ ;(yason:encode-object-element "source-type" source-type) |
|
80 |
+ (yason:encode-object-element "description" description) |
|
81 |
+ (yason:with-object-element ("items") |
|
82 |
+ (yason:with-array () |
|
83 |
+ (dolist (item item-storage-info) |
|
84 |
+ (with-simple-restart (continue "Skip item ~s" (car item)) |
|
85 |
+ (encode-item item)))))))))) |
|
50 | 86 |
|
51 | 87 |
(defun older-than-a-week (date) |
52 | 88 |
(let ((week-ago (local-time:timestamp- (local-time:now) |
53 | 89 |
7 :day))) |
54 | 90 |
(local-time:timestamp< date week-ago))) |
55 | 91 |
|
92 |
+(defmethod get-id ((feed alimenta:feed)) |
|
93 |
+ (let* ((link (alimenta:feed-link feed)) |
|
94 |
+ (host (puri:uri-host link))) |
|
95 |
+ (concat host "-" (sha256-string link) "/"))) |
|
96 |
+ |
|
97 |
+(defun get-feed-store-name (feed directory) |
|
98 |
+ (merge-pathnames (get-id feed) |
|
99 |
+ directory)) |
|
100 |
+ |
|
101 |
+(defmethod store ((feed alimenta:feed) directory) |
|
102 |
+ (declare (optimize (debug 3))) |
|
103 |
+ (with-accessors ((description alimenta:description) |
|
104 |
+ (feed-link alimenta:feed-link) |
|
105 |
+ (items alimenta:items) |
|
106 |
+ (link alimenta:link) |
|
107 |
+ (source-type alimenta:source-type) |
|
108 |
+ (title alimenta:title)) feed |
|
109 |
+ (prog1-let ((feed-title title) |
|
110 |
+ (feed-store (get-feed-store-name feed directory))) |
|
111 |
+ (ensure-directories-exist feed-store) |
|
112 |
+ (with-open-file (index (merge-pathnames "index.json" feed-store) :direction :output) |
|
113 |
+ (encode-feed-as-json feed |
|
114 |
+ (store items feed-store) |
|
115 |
+ feed-store |
|
116 |
+ index))))) |
|
117 |
+ |
|
56 | 118 |
(defmethod store ((items sequence) directory) |
119 |
+ (declare (optimize (debug 3))) |
|
57 | 120 |
(map 'list (lambda (item) (store item directory)) |
58 | 121 |
(stable-sort |
59 | 122 |
(sort (remove-if #'older-than-a-week items :key #'alimenta:date) |
... | ... |
@@ -63,16 +126,17 @@ |
63 | 126 |
:key #'alimenta:date))) |
64 | 127 |
|
65 | 128 |
(defmethod get-id ((item alimenta:item)) |
66 |
- (let* ((digester (ironclad:make-digesting-stream :sha256)) |
|
67 |
- (digest-stream (flexi-streams:make-flexi-stream digester))) |
|
68 |
- (princ (alimenta:id item) digest-stream) |
|
69 |
- (concatenate 'string |
|
70 |
- (local-time:format-timestring nil (alimenta:date item)) |
|
71 |
- "-" |
|
72 |
- (crypto:byte-array-to-hex-string (crypto:produce-digest digester)) |
|
73 |
- ".json"))) |
|
129 |
+ (concatenate 'string |
|
130 |
+ (local-time:format-timestring nil (alimenta:date item)) |
|
131 |
+ "-" |
|
132 |
+ (sha256-string (alimenta:id item)) |
|
133 |
+ ".json")) |
|
74 | 134 |
|
75 |
-(defmethod store ((item alimenta:item) directory) |
|
135 |
+(defun get-item-store-name (item directory) |
|
136 |
+ (let ((id (get-id item))) |
|
137 |
+ (merge-pathnames (make-pathname :name id) directory))) |
|
138 |
+ |
|
139 |
+(defmethod yason:encode ((item alimenta:item) &optional stream) |
|
76 | 140 |
(with-accessors ((author alimenta::author) |
77 | 141 |
(content alimenta:content) |
78 | 142 |
(date alimenta:date) |
... | ... |
@@ -80,17 +144,22 @@ |
80 | 144 |
(link alimenta:link) |
81 | 145 |
(title alimenta:title)) item |
82 | 146 |
(let* ((date (local-time:format-timestring nil date))) |
83 |
- (prog1-let ((item-title title) |
|
84 |
- (fn (get-id item))) |
|
85 |
- (with-open-file (item-f (merge-pathnames fn directory) :direction :output) |
|
86 |
- (yason:with-output (item-f :indent t) |
|
87 |
- (yason:with-object () |
|
88 |
- (yason:encode-object-element "title" title) |
|
89 |
- (yason:encode-object-element "date" date) |
|
90 |
- (yason:encode-object-element "author" title) |
|
91 |
- (yason:encode-object-element "id" (princ-to-string id)) |
|
92 |
- (yason:encode-object-element "link" link) |
|
93 |
- (yason:encode-object-element "content" content))))) ))) |
|
147 |
+ (yason:with-output (stream :indent t) |
|
148 |
+ (yason:with-object () |
|
149 |
+ (yason:encode-object-element "title" title) |
|
150 |
+ (yason:encode-object-element "date" date) |
|
151 |
+ (yason:encode-object-element "author" title) |
|
152 |
+ (yason:encode-object-element "id" (princ-to-string id)) |
|
153 |
+ (yason:encode-object-element "link" link) |
|
154 |
+ (yason:encode-object-element "content" content))))) |
|
155 |
+ item) |
|
156 |
+ |
|
157 |
+(defmethod store ((item alimenta:item) directory) |
|
158 |
+ (declare (optimize (debug 3))) |
|
159 |
+ (prog1-let ((item-title (alimenta:title item)) |
|
160 |
+ (fn (get-item-store-name item directory))) |
|
161 |
+ (with-open-file (item-f fn :direction :output) |
|
162 |
+ (yason:encode item item-f)))) |
|
94 | 163 |
|
95 | 164 |
|
96 | 165 |
(defun init-feeds (&key feed-list archive-root) |
... | ... |
@@ -102,12 +171,14 @@ |
102 | 171 |
(ubiquitous:defaulted-value default-root :archive :root)))) |
103 | 172 |
|
104 | 173 |
(defun add-feed (feed) |
174 |
+ (declare (optimize (debug 3))) |
|
105 | 175 |
(init-feeds) |
106 | 176 |
(pushnew feed |
107 | 177 |
(ubiquitous:value :feeds) |
108 | 178 |
:test #'equalp)) |
109 | 179 |
|
110 | 180 |
(defun safe-pull-feed (feed-url) |
181 |
+ (declare (optimize (debug 3))) |
|
111 | 182 |
(let ((pop-times 0)) |
112 | 183 |
(handler-bind |
113 | 184 |
((condition |
... | ... |
@@ -146,10 +217,21 @@ |
146 | 217 |
(mapcar (lambda (url feed-data) |
147 | 218 |
(yason:with-object () |
148 | 219 |
(yason:encode-object-element "url" url) |
149 |
- (destructuring-bind (title path) feed-data |
|
150 |
- (yason:encode-object-element "title" title) |
|
151 |
- (yason:encode-object-element "path" |
|
152 |
- (princ-to-string |
|
153 |
- (uiop:enough-pathname path *feed-base*)))))) |
|
154 |
- *feeds* |
|
155 |
- paths))))))))))) |
|
220 |
+ (when feed-data |
|
221 |
+ (destructuring-bind (title path) feed-data |
|
222 |
+ (yason:encode-object-element "title" title) |
|
223 |
+ (yason:encode-object-element "path" |
|
224 |
+ (princ-to-string |
|
225 |
+ (uiop:enough-pathname path *feed-base*))))))) |
|
226 |
+ *feeds* |
|
227 |
+ paths))))))))))) |
|
228 |
+ |
|
229 |
+ |
|
230 |
+(defun command-line-main () |
|
231 |
+ (handler-bind ((t (lambda (c) |
|
232 |
+ c |
|
233 |
+ (if (find-restart 'fix-pathname) |
|
234 |
+ (fix-pathname) |
|
235 |
+ (progn (format t "~&Skip a feed...~%") |
|
236 |
+ (continue)))))) |
|
237 |
+ (archive-feeds))) |