~ubuntu-branches/ubuntu/trusty/cl-asdf/trusty-proposed

« back to all changes in this revision

Viewing changes to component.lisp

  • Committer: Package Import Robot
  • Author(s): Francois-Rene Rideau
  • Date: 2013-05-27 22:44:50 UTC
  • mfrom: (1.1.28)
  • Revision ID: package-import@ubuntu.com-20130527224450-4bddztgqi7q1uzn7
Tags: 2:3.0.1.2-1
ASDF 3.0.1.2 fixes issues with the debian package itself.
It also includes fixes to run-program and run-shell-command.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;;; -------------------------------------------------------------------------
 
2
;;;; Components
 
3
 
 
4
(asdf/package:define-package :asdf/component
 
5
  (:recycle :asdf/component :asdf)
 
6
  (:use :asdf/common-lisp :asdf/driver :asdf/upgrade)
 
7
  (:export
 
8
   #:component #:component-find-path
 
9
   #:component-name #:component-pathname #:component-relative-pathname
 
10
   #:component-parent #:component-system #:component-parent-pathname
 
11
   #:child-component #:parent-component #:module
 
12
   #:file-component
 
13
   #:source-file #:c-source-file #:java-source-file
 
14
   #:static-file #:doc-file #:html-file
 
15
   #:file-type
 
16
   #:source-file-type #:source-file-explicit-type ;; backward-compatibility
 
17
   #:component-in-order-to #:component-sideway-dependencies
 
18
   #:component-if-feature #:around-compile-hook
 
19
   #:component-description #:component-long-description
 
20
   #:component-version #:version-satisfies
 
21
   #:component-inline-methods ;; backward-compatibility only. DO NOT USE!
 
22
   #:component-operation-times ;; For internal use only.
 
23
   ;; portable ASDF encoding and implementation-specific external-format
 
24
   #:component-external-format #:component-encoding
 
25
   #:component-children-by-name #:component-children #:compute-children-by-name
 
26
   #:component-build-operation
 
27
   #:module-default-component-class
 
28
   #:module-components ;; backward-compatibility. DO NOT USE.
 
29
   #:sub-components
 
30
 
 
31
   ;; Internals we'd like to share with the ASDF package, especially for upgrade purposes
 
32
   #:name #:version #:description #:long-description #:author #:maintainer #:licence
 
33
   #:components-by-name #:components
 
34
   #:children #:children-by-name #:default-component-class
 
35
   #:author #:maintainer #:licence #:source-file #:defsystem-depends-on
 
36
   #:sideway-dependencies #:if-feature #:in-order-to #:inline-methods
 
37
   #:relative-pathname #:absolute-pathname #:operation-times #:around-compile
 
38
   #:%encoding #:properties #:component-properties #:parent))
 
39
(in-package :asdf/component)
 
40
 
 
41
(with-upgradability ()
 
42
  (defgeneric component-name (component)
 
43
    (:documentation "Name of the COMPONENT, unique relative to its parent"))
 
44
  (defgeneric component-system (component)
 
45
    (:documentation "Find the top-level system containing COMPONENT"))
 
46
  (defgeneric component-pathname (component)
 
47
    (:documentation "Extracts the pathname applicable for a particular component."))
 
48
  (defgeneric (component-relative-pathname) (component)
 
49
    (:documentation "Returns a pathname for the component argument intended to be
 
50
interpreted relative to the pathname of that component's parent.
 
51
Despite the function's name, the return value may be an absolute
 
52
pathname, because an absolute pathname may be interpreted relative to
 
53
another pathname in a degenerate way."))
 
54
  (defgeneric component-external-format (component))
 
55
  (defgeneric component-encoding (component))
 
56
  (defgeneric version-satisfies (component version))
 
57
  (defgeneric component-version (component))
 
58
  (defgeneric (setf component-version) (new-version component))
 
59
  (defgeneric component-parent (component))
 
60
  (defmethod component-parent ((component null)) (declare (ignorable component)) nil)
 
61
 
 
62
  ;; Backward compatible way of computing the FILE-TYPE of a component.
 
63
  ;; TODO: find users, have them stop using that, remove it for ASDF4.
 
64
  (defgeneric (source-file-type) (component system)))
 
65
 
 
66
(when-upgrading (:when (find-class 'component nil))
 
67
  (defmethod reinitialize-instance :after ((c component) &rest initargs &key)
 
68
    (declare (ignorable c initargs)) (values)))
 
69
 
 
70
(with-upgradability ()
 
71
  (defclass component ()
 
72
    ((name :accessor component-name :initarg :name :type string :documentation
 
73
           "Component name: designator for a string composed of portable pathname characters")
 
74
     ;; We might want to constrain version with
 
75
     ;; :type (and string (satisfies parse-version))
 
76
     ;; but we cannot until we fix all systems that don't use it correctly!
 
77
     (version :accessor component-version :initarg :version :initform nil)
 
78
     (description :accessor component-description :initarg :description :initform nil)
 
79
     (long-description :accessor component-long-description :initarg :long-description :initform nil)
 
80
     (sideway-dependencies :accessor component-sideway-dependencies :initform nil)
 
81
     (if-feature :accessor component-if-feature :initform nil :initarg :if-feature)
 
82
     ;; In the ASDF object model, dependencies exist between *actions*,
 
83
     ;; where an action is a pair of an operation and a component.
 
84
     ;; Dependencies are represented as alists of operations
 
85
     ;; to a list where each entry is a pair of an operation and a list of component specifiers.
 
86
     ;; Up until ASDF 2.26.9, there used to be two kinds of dependencies:
 
87
     ;; in-order-to and do-first, each stored in its own slot. Now there is only in-order-to.
 
88
     ;; in-order-to used to represent things that modify the filesystem (such as compiling a fasl)
 
89
     ;; and do-first things that modify the current image (such as loading a fasl).
 
90
     ;; These are now unified because we now correctly propagate timestamps between dependencies.
 
91
     ;; Happily, no one seems to have used do-first too much (especially since until ASDF 2.017,
 
92
     ;; anything you specified was overridden by ASDF itself anyway), but the name in-order-to remains.
 
93
     ;; The names are bad, but they have been the official API since Dan Barlow's ASDF 1.52!
 
94
     ;; LispWorks's defsystem has caused-by and requires for in-order-to and do-first respectively.
 
95
     ;; Maybe rename the slots in ASDF? But that's not very backward-compatible.
 
96
     ;; See our ASDF 2 paper for more complete explanations.
 
97
     (in-order-to :initform nil :initarg :in-order-to
 
98
                  :accessor component-in-order-to)
 
99
     ;; methods defined using the "inline" style inside a defsystem form:
 
100
     ;; need to store them somewhere so we can delete them when the system
 
101
     ;; is re-evaluated.
 
102
     (inline-methods :accessor component-inline-methods :initform nil) ;; OBSOLETE! DELETE THIS IF NO ONE USES.
 
103
     ;; ASDF4: rename it from relative-pathname to specified-pathname. It need not be relative.
 
104
     ;; There is no initform and no direct accessor for this specified pathname,
 
105
     ;; so we only access the information through appropriate methods, after it has been processed.
 
106
     ;; Unhappily, some braindead systems directly access the slot. Make them stop before ASDF4.
 
107
     (relative-pathname :initarg :pathname)
 
108
     ;; The absolute-pathname is computed based on relative-pathname and parent pathname.
 
109
     ;; The slot is but a cache used by component-pathname.
 
110
     (absolute-pathname)
 
111
     (operation-times :initform (make-hash-table)
 
112
                      :accessor component-operation-times)
 
113
     (around-compile :initarg :around-compile)
 
114
     ;; Properties are for backward-compatibility with ASDF2 only. DO NOT USE!
 
115
     (properties :accessor component-properties :initarg :properties
 
116
                 :initform nil)
 
117
     (%encoding :accessor %component-encoding :initform nil :initarg :encoding)
 
118
     ;; For backward-compatibility, this slot is part of component rather than of child-component. ASDF4: stop it.
 
119
     (parent :initarg :parent :initform nil :reader component-parent)
 
120
     (build-operation
 
121
      :initarg :build-operation :initform nil :reader component-build-operation)))
 
122
 
 
123
  (defun component-find-path (component)
 
124
    (check-type component (or null component))
 
125
    (reverse
 
126
     (loop :for c = component :then (component-parent c)
 
127
           :while c :collect (component-name c))))
 
128
 
 
129
  (defmethod print-object ((c component) stream)
 
130
    (print-unreadable-object (c stream :type t :identity nil)
 
131
      (format stream "~{~S~^ ~}" (component-find-path c))))
 
132
 
 
133
  (defmethod component-system ((component component))
 
134
    (if-let (system (component-parent component))
 
135
      (component-system system)
 
136
      component)))
 
137
 
 
138
 
 
139
;;;; Component hierarchy within a system
 
140
;; The tree typically but not necessarily follows the filesystem hierarchy.
 
141
(with-upgradability ()
 
142
  (defclass child-component (component) ())
 
143
 
 
144
  (defclass file-component (child-component)
 
145
    ((type :accessor file-type :initarg :type))) ; no default
 
146
  (defclass source-file (file-component)
 
147
    ((type :accessor source-file-explicit-type ;; backward-compatibility
 
148
           :initform nil))) ;; NB: many systems have come to rely on this default.
 
149
  (defclass c-source-file (source-file)
 
150
    ((type :initform "c")))
 
151
  (defclass java-source-file (source-file)
 
152
    ((type :initform "java")))
 
153
  (defclass static-file (source-file)
 
154
    ((type :initform nil)))
 
155
  (defclass doc-file (static-file) ())
 
156
  (defclass html-file (doc-file)
 
157
    ((type :initform "html")))
 
158
 
 
159
  (defclass parent-component (component)
 
160
    ((children
 
161
      :initform nil
 
162
      :initarg :components
 
163
      :reader module-components ; backward-compatibility
 
164
      :accessor component-children)
 
165
     (children-by-name
 
166
      :reader module-components-by-name ; backward-compatibility
 
167
      :accessor component-children-by-name)
 
168
     (default-component-class
 
169
      :initform nil
 
170
      :initarg :default-component-class
 
171
      :accessor module-default-component-class))))
 
172
 
 
173
(with-upgradability ()
 
174
  (defun compute-children-by-name (parent &key only-if-needed-p)
 
175
    (unless (and only-if-needed-p (slot-boundp parent 'children-by-name))
 
176
      (let ((hash (make-hash-table :test 'equal)))
 
177
        (setf (component-children-by-name parent) hash)
 
178
        (loop :for c :in (component-children parent)
 
179
              :for name = (component-name c)
 
180
              :for previous = (gethash name hash)
 
181
              :do (when previous (error 'duplicate-names :name name))
 
182
                  (setf (gethash name hash) c))
 
183
        hash))))
 
184
 
 
185
(when-upgrading (:when (find-class 'module nil))
 
186
  (defmethod reinitialize-instance :after ((m module) &rest initargs &key)
 
187
    (declare (ignorable m initargs)) (values))
 
188
  (defmethod update-instance-for-redefined-class :after
 
189
      ((m module) added deleted plist &key)
 
190
    (declare (ignorable m added deleted plist))
 
191
    (when (and (member 'children added) (member 'components deleted))
 
192
      (setf (slot-value m 'children)
 
193
            ;; old ECLs provide an alist instead of a plist(!)
 
194
            (if (or #+ecl (consp (first plist))) (or #+ecl (cdr (assoc 'components plist)))
 
195
                (getf plist 'components)))
 
196
      (compute-children-by-name m))))
 
197
 
 
198
(with-upgradability ()
 
199
  (defclass module (child-component parent-component)
 
200
    (#+clisp (components)))) ;; backward compatibility during upgrade only
 
201
 
 
202
 
 
203
;;;; component pathnames
 
204
(with-upgradability ()
 
205
  (defgeneric* (component-parent-pathname) (component))
 
206
  (defmethod component-parent-pathname (component)
 
207
    (component-pathname (component-parent component)))
 
208
 
 
209
  (defmethod component-pathname ((component component))
 
210
    (if (slot-boundp component 'absolute-pathname)
 
211
        (slot-value component 'absolute-pathname)
 
212
        (let ((pathname
 
213
                (merge-pathnames*
 
214
                 (component-relative-pathname component)
 
215
                 (pathname-directory-pathname (component-parent-pathname component)))))
 
216
          (unless (or (null pathname) (absolute-pathname-p pathname))
 
217
            (error (compatfmt "~@<Invalid relative pathname ~S for component ~S~@:>")
 
218
                   pathname (component-find-path component)))
 
219
          (setf (slot-value component 'absolute-pathname) pathname)
 
220
          pathname)))
 
221
 
 
222
  (defmethod component-relative-pathname ((component component))
 
223
    ;; source-file-type is backward-compatibility with ASDF1;
 
224
    ;; we ought to be able to extract this from the component alone with COMPONENT-TYPE.
 
225
    ;; TODO: track who uses it, and have them not use it anymore.
 
226
    (parse-unix-namestring
 
227
     (or (and (slot-boundp component 'relative-pathname)
 
228
              (slot-value component 'relative-pathname))
 
229
         (component-name component))
 
230
     :want-relative t
 
231
     :type (source-file-type component (component-system component))
 
232
     :defaults (component-parent-pathname component)))
 
233
 
 
234
  (defmethod source-file-type ((component parent-component) system)
 
235
    (declare (ignorable component system))
 
236
    :directory)
 
237
 
 
238
  (defmethod source-file-type ((component file-component) system)
 
239
    (declare (ignorable system))
 
240
    (file-type component)))
 
241
 
 
242
 
 
243
;;;; Encodings
 
244
(with-upgradability ()
 
245
  (defmethod component-encoding ((c component))
 
246
    (or (loop :for x = c :then (component-parent x)
 
247
              :while x :thereis (%component-encoding x))
 
248
        (detect-encoding (component-pathname c))))
 
249
 
 
250
  (defmethod component-external-format ((c component))
 
251
    (encoding-external-format (component-encoding c))))
 
252
 
 
253
 
 
254
;;;; around-compile-hook
 
255
(with-upgradability ()
 
256
  (defgeneric around-compile-hook (component))
 
257
  (defmethod around-compile-hook ((c component))
 
258
    (cond
 
259
      ((slot-boundp c 'around-compile)
 
260
       (slot-value c 'around-compile))
 
261
      ((component-parent c)
 
262
       (around-compile-hook (component-parent c))))))
 
263
 
 
264
 
 
265
;;;; version-satisfies
 
266
(with-upgradability ()
 
267
  (defmethod version-satisfies ((c component) version)
 
268
    (unless (and version (slot-boundp c 'version))
 
269
      (when version
 
270
        (warn "Requested version ~S but component ~S has no version" version c))
 
271
      (return-from version-satisfies t))
 
272
    (version-satisfies (component-version c) version))
 
273
 
 
274
  (defmethod version-satisfies ((cver string) version)
 
275
    (version<= version cver)))
 
276
 
 
277
 
 
278
;;; all sub-components (of a given type)
 
279
(with-upgradability ()
 
280
  (defun sub-components (component &key (type t))
 
281
    (while-collecting (c)
 
282
      (labels ((recurse (x)
 
283
                 (when (if-let (it (component-if-feature x)) (featurep it) t)
 
284
                   (when (typep x type)
 
285
                     (c x))
 
286
                   (when (typep x 'parent-component)
 
287
                     (map () #'recurse (component-children x))))))
 
288
        (recurse component)))))
 
289