git.fiddlerwoaroof.com
Browse code

Fix pathnames for sbcl

fiddlerwoaroof authored on 15/10/2016 09:58:45
Showing 2 changed files
... ...
@@ -8,6 +8,7 @@
8 8
                #:ironclad
9 9
                #:local-time
10 10
                #:serapeum
11
+               #:uiop
11 12
                #:ubiquitous
12 13
                #:yason)
13 14
   :serial t
... ...
@@ -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)))