source: tags/1.5.0/contrib/abcl-asdf/maven.lisp

Last change on this file was 15020, checked in by Mark Evenson, 7 years ago

asdf-mvn-module: fix test invocation

Remove duplicate defintion of RESOLVE-MULTIPLE-MAVEN-DEPENDENCIES

File size: 24.1 KB
Line 
1;;;; Use the Aether system in a localy installed Maven3 distribution to download
2;;;; and install JVM artifact dependencies.
3
4;;; TODO refactor out aether.lisp
5
6#|
7
8# Implementation
9
10Not necessarily multi-threaded safe, and unclear how much work that
11would be, as it is unknown how the Maven implementation behaves.
12
13## Installing Maven
14http://maven.apache.org/download.html
15
16## Current Javadoc for Maven Aether connector
17http://sonatype.github.com/sonatype-aether/apidocs/overview-summary.html
18
19## Incomplete, seemingly often wrong
20https://docs.sonatype.org/display/AETHER/Home
21
22Note that this is not an implementation of Maven per se, but the use
23of the Maven Aether connector infrastructure.  Among other things, this means
24that the Maven specific "~/.m2/settings.xml" file is NOT parsed for settings.
25
26|#
27
28;;; N.b. evaluated *after* we load the ABCL specific modifications of
29;;;      ASDF in abcl-asdf.lisp
30
31(in-package :abcl-asdf)
32
33(require :abcl-contrib)
34(require :jss)
35
36#|
37Test:
38(abcl-asdf:resolve "org.slf4j:slf4j-api:1.6.1")
39
40(abcl-asdf:resolve "org.apache.maven:maven-aether-provider:3.0.4")
41
42(abcl-asdf:resolve "com.google.gwt:gwt-user")
43
44|#
45
46(defparameter *mavens* 
47  (if (find :windows *features*)
48      '("mvn" "mvn.bat" "mvn3.bat" "mvn.cmd")
49      '("mvn3" "mvn"
50        ;; MacPorts
51        "/opt/local/bin/mvn3"))
52  "Locations to search for the Maven executable.")
53
54(defun find-mvn () 
55  "Attempt to find a suitable Maven ('mvn') executable on the hosting operating system.
56
57Returns the path of the Maven executable or nil if none are found.
58
59Returns the version of Maven found as the second value.
60
61Emits warnings if not able to find a suitable executable."
62
63  (let ((m2-home (ext:getenv "M2_HOME"))
64        (m2 (ext:getenv "M2"))
65        (mvn-executable (if (find :unix *features*)
66                            "mvn"
67                            "mvn.bat")))
68    (when (and m2-home (probe-file m2-home))
69      (let* ((m2-home (truename m2-home))
70             (mvn-path (merge-pathnames 
71                        (format nil "bin/~A" mvn-executable)
72                        m2-home))
73             (mvn (truename mvn-path)))
74        (if mvn
75            (values (return-from find-mvn mvn)
76                    (ensure-mvn-version))
77            (warn "M2_HOME was set to '~A' in the process environment but '~A' doesn't exist." 
78                  m2-home mvn-path))))
79    (when (and m2 (probe-file m2))
80      (let* ((m2 (truename m2))
81             (mvn-path (merge-pathnames mvn-executable m2))
82             (mvn (truename mvn-path)))
83        (if mvn
84            (values (return-from find-mvn mvn)
85                    (ensure-mvn-version))
86            (warn "M2 was set to '~A' in the process environment but '~A' doesn't exist." 
87                  m2 mvn-path))))
88    (let* ((which-cmd 
89            (if (find :unix *features*)
90                "which" 
91                ;; Starting with Windows Server 2003
92                "where.exe"))
93           (which-cmd-p 
94            (handler-case 
95                (sys:run-program which-cmd nil)
96              (t () nil))))
97      (when which-cmd-p
98        (dolist (mvn-path *mavens*)
99          (let ((mvn 
100                 (handler-case 
101                     (truename (read-line (sys:process-output 
102                                           (sys:run-program 
103                                            which-cmd `(,mvn-path))))) 
104                   (end-of-file () nil)
105                   (t (e) 
106                     (format cl:*load-verbose*
107                             "~&; abcl-asdf; Failed to find Maven executable '~A' in PATH because~&~A" 
108                             mvn-path e)))))
109            (when mvn
110              (return-from find-mvn mvn)))))))
111  (warn "Unable to locate Maven executable to find Maven Aether adaptors."))
112
113(defun find-mvn-libs ()
114  (unless (find-mvn)
115    (warn "Failed to find Maven executable to determine Aether library location.  Continuing anyways."))
116  (some 
117   (lambda (d)
118     (when (and
119            (pathnamep d)
120            (directory (merge-pathnames "maven-core*.jar" d)))
121       (truename d)))
122   (list (ignore-errors
123           (make-pathname :defaults (merge-pathnames "../lib/" (find-mvn))
124                          :name nil :type nil))
125         (ignore-errors
126           (make-pathname :defaults (merge-pathnames "lib/" (mvn-home))
127                          :name nil :type nil))
128         ;; library location for homebrew maven package on OS X
129         (ignore-errors
130           (make-pathname :defaults (merge-pathnames "../libexec/lib/" (find-mvn))
131                          :name nil :type nil))
132         #p"/usr/local/share/java/maven3/lib/" ;; FreeBSD ports
133         #p"/usr/local/maven/lib/"))) ;; OpenBSD location suggested by Timo MyyrÀ
134
135(defparameter *mvn-libs-directory*
136  nil
137  "Location of 'maven-core-3.<m>.<p>.jar', 'maven-embedder-3.<m>.<p>.jar' etc.")
138
139(defun mvn-version ()
140  "Return the Maven version used by the Aether connector located by
141  FIND-MVN as a list of (MAJOR MINOR PATHLEVEL) integers.
142
143Signals a simple-error with additional information if this attempt fails."
144  (handler-case 
145      (let* ((process (sys:run-program (truename (find-mvn)) '("-version")))
146             (output (sys:process-output process))
147             (pattern (#"compile"
148                       'regex.Pattern
149                       "Apache Maven ([0-9]+)\\.([0-9]+)\\.([0-9]+)"))
150             lines)
151        (do ((line (read-line output nil :eof) 
152                   (read-line output nil :eof)))
153            ((or (not line) (eq line :eof)) nil)
154          (push line lines)
155          (let ((matcher (#"matcher" pattern line)))
156            (when (#"find" matcher)
157              (return-from mvn-version
158                (mapcar #'parse-integer 
159                        `(,(#"group" matcher 1) 
160                           ,(#"group" matcher 2) 
161                           ,(#"group" matcher 3)))))))
162        (when lines 
163          (signal "No parseable Maven version found in ~{~&  ~A~}" (nreverse lines)))
164        (let ((error (sys:process-error process)))
165          (do ((line (read-line error nil :eof) 
166                     (read-line error nil :eof)))
167              ((or (not line) (eq line :eof)) nil)
168            (push line lines)
169            (signal "Invocation of Maven returned the error ~{~&  ~A~}" (nreverse lines)))))
170    (t (e) 
171      (error "Failed to determine Maven version: ~A." e))))
172
173(defun mvn-home ()
174  "If the Maven executable can be invoked, introspect the value
175  reported as Maven home."
176  (handler-case 
177      (multiple-value-bind (output error-output status)
178          (uiop/run-program:run-program
179           (format nil "~a --version" (truename (find-mvn)))
180           :output :string
181           :error-output :string)
182        (unless (zerop status)
183          (error "Failed to invoke Maven executable to introspect library locations: ~a." error-output))
184        (let ((pattern (#"compile"
185                        'regex.Pattern
186                        "Maven home: (.+)$")))
187          (with-input-from-string (s output)
188            (do ((line (read-line s nil :eof) 
189                       (read-line s nil :eof)))
190                ((or (not line) (eq line :eof)) nil)
191              (let ((matcher (#"matcher" pattern line)))
192                (when (#"find" matcher)
193                  (return-from mvn-home
194                    (uiop/pathname:ensure-directory-pathname (#"group" matcher 1)))))))))
195    (subprocess-error (e)
196          (error "Failed to invoke Maven executable to introspect library locations: ~a." e))))
197                       
198(defun ensure-mvn-version ()
199  "Return t if Maven version is 3.0.3 or greater."
200  (let* ((version (mvn-version))
201         (major (first version))
202         (minor (second version))
203         (patch (third version)))
204    (values
205     (or 
206      (and (>= major 3)
207           (>= minor 1))
208      (and (>= major 3)
209           (>= minor 0)
210           (>= patch 3)))
211     (list major minor patch))))
212
213(define-condition no-aether-maven-libs (error)
214  ((locations :initarg :locations
215              :initform nil
216              :reader locations))
217  (:report (lambda (condition stream)
218             (format stream "No Maven Aether libraries found locally in '~a'."
219                     (locations condition)))))
220             
221(defparameter *init* nil)
222 
223(defun init (&optional &key (force nil))
224  "Run the initialization strategy to bootstrap a Maven dependency node.
225
226Set *MVN-LIBS-DIRECTORY* to an explicit value before running this
227function in order to bypass the dynamic introspection of the location
228of the mvn executable with an explicit value."
229  (when force
230    (setf *session* nil
231          *repository-system* nil))
232  (unless (or force *mvn-libs-directory*)
233    (setf *mvn-libs-directory* (find-mvn-libs)))
234  (unless (and *mvn-libs-directory*
235               (probe-file *mvn-libs-directory*))
236    ;; FIXME Remove warning; put message in restart
237    (warn "Please obtain and install maven-3.0.3 or later locally from <http://maven.apache.org/download.html>, then set ABCL-ASDF:*MVN-LIBS-DIRECTORY* to the directory containing maven-core-3.*.jar et. al.")
238    (error (make-condition 'abcl-asdf::no-aether-maven-libs
239                           :locations (list *mvn-libs-directory*))))
240  (unless (ensure-mvn-version)
241    (error "We need maven-3.0.3 or later."))
242  (add-directory-jars-to-class-path *mvn-libs-directory* nil)
243  (setf *init* t))
244
245(defmacro with-aether ((&optional aether-directory) &body body)
246  "Ensure that the code in BODY is executed with the Maven Aether libraries on the classpath."
247  `(progn
248     (declare (ignore aether-directory)) ;;; FIXME
249     (unless abcl-asdf::*init*
250       (abcl-asdf::init))
251     ,@body))
252
253(defun find-http-wagon ()
254  "Find an implementation of the object that provides access to http and https resources.
255
256Supposedly configurable with the java.net.protocols (c.f. reference
257maso2000 in the Manual.)"
258  (handler-case 
259      ;; maven-3.0.4
260      (java:jnew "org.apache.maven.wagon.providers.http.HttpWagon") 
261    (error () 
262      ;; maven-3.0.3 reported as not working with all needed functionality
263      (java:jnew  "org.apache.maven.wagon.providers.http.LightweightHttpWagon"))))
264
265(defun make-wagon-provider ()
266  "Returns an implementation of the org.sonatype.aether.connector.wagon.WagonProvider contract.
267
268The implementation is specified as Lisp closures.  Currently, it only
269specializes the lookup() method if passed an 'http' or an 'https' role
270hint."
271  (unless *init* (init))
272  (java:jinterface-implementation 
273   (#"getName" 
274    (or
275     (ignore-errors  ;; Maven 3.2.5+
276       (jss:find-java-class 'aether.transport.wagon.WagonProvider))
277     (ignore-errors  ;; Maven 3.1.0+
278       (jss:find-java-class 'aether.connector.wagon.WagonProvider))
279     (ignore-errors  ;; Maven 3.0.x
280       (jss:find-java-class 'org.sonatype.aether.connector.wagon.WagonProvider))))
281   "lookup"
282   (lambda (role-hint)
283     (cond 
284       ((find role-hint '("http" "https") :test #'string-equal)
285        (find-http-wagon))
286       (t
287        (progn 
288          (format cl:*load-verbose*
289                  "~&; abcl-asdf; WagonProvider stub passed '~A' as a hint it couldn't satisfy.~%"
290                  role-hint)
291          java:+null+))))
292   "release"
293   (lambda (wagon)
294     (declare (ignore wagon)))))
295
296(defun find-service-locator ()
297  (or 
298   (ignore-errors
299     ;; maven-3.1.0
300     (#"newServiceLocator" 'org.apache.maven.repository.internal.MavenRepositorySystemUtils)) 
301   (ignore-errors
302     ;; maven-3.0.4
303     (java:jnew "org.apache.maven.repository.internal.MavenServiceLocator")) 
304   (ignore-errors
305     (java:jnew "org.apache.maven.repository.internal.DefaultServiceLocator"))
306   (ignore-errors
307     ;; maven-3.1.0 using org.eclipse.aether...
308     (jss:find-java-class 'aether.impl.DefaultServiceLocator))))
309
310(defun make-repository-system ()
311  (unless *init* (init))
312  (let ((locator 
313         (find-service-locator))
314        (wagon-provider-class 
315         (or
316          (ignore-errors ;; Maven-3.3.x
317            (jss:find-java-class 'connector.transport.TransporterFactory))
318          (ignore-errors ;; Maven-3.2.5
319            (jss:find-java-class 'org.eclipse.aether.transport.wagon.WagonProvider))
320          (ignore-errors  ;; Maven-3.1.x
321            (jss:find-java-class 'aether.connector.wagon.WagonProvider))
322          (ignore-errors 
323            (java:jclass "org.sonatype.aether.connector.wagon.WagonProvider"))))
324        (wagon-repository-connector-factory-class
325         (or 
326          (ignore-errors 
327            (jss:find-java-class 'org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory))
328          (ignore-errors 
329            (jss:find-java-class 'aether.connector.wagon.WagonRepositoryConnectorFactory))
330          (ignore-errors 
331            (java:jclass "org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory"))))
332        (repository-connector-factory-class 
333         (or
334          (ignore-errors
335            (jss:find-java-class 'org.eclipse.aether.spi.connector.RepositoryConnectorFactory))
336          (ignore-errors
337            (jss:find-java-class 'aether.spi.connector.RepositoryConnectorFactory))
338          (ignore-errors 
339            (java:jclass "org.sonatype.aether.spi.connector.RepositoryConnectorFactory"))))
340        (repository-system-class
341         (or
342          (ignore-errors 
343            (jss:find-java-class 'org.eclipse.aether.RepositorySystem))
344          (ignore-errors 
345            (jss:find-java-class 'aether.RepositorySystem))
346          (ignore-errors
347            (java:jclass "org.sonatype.aether.RepositorySystem")))))
348
349    (if (equal wagon-provider-class (ignore-errors (jss:find-java-class 'TransporterFactory)))
350        ;;; Maven-3.3.3
351        (let ((wagon-transporter-factory (jss:new 'WagonTransporterFactory)))
352          (#"setWagonProvider" wagon-transporter-factory (make-wagon-provider))
353          (#"setServices" locator
354                          wagon-provider-class
355                          (java:jarray-from-list (list wagon-transporter-factory))))
356        (#"setServices" locator
357                        wagon-provider-class
358                        (java:jarray-from-list
359                         (list (make-wagon-provider)))))
360    (#"addService" locator
361                   repository-connector-factory-class
362                   wagon-repository-connector-factory-class)
363    (values (#"getService" locator
364                           repository-system-class)
365            locator)))
366
367(defun make-session (repository-system)
368  "Construct a new aether.RepositorySystemSession from the specified REPOSITORY-SYSTEM."
369  (let ((session
370         (or 
371          (ignore-errors (#"newSession"
372                          'org.apache.maven.repository.internal.MavenRepositorySystemUtils))
373          (ignore-errors (java:jnew (jss:find-java-class "MavenRepositorySystemSession")))))
374        (local-repository 
375         (java:jnew (jss:find-java-class "LocalRepository")
376                    (namestring (merge-pathnames ".m2/repository/"
377                                                 (user-homedir-pathname))))))
378    (#"setLocalRepositoryManager" 
379     session
380     (or 
381      (ignore-errors      ;; maven-3.1.0
382        (#"newLocalRepositoryManager" 
383         repository-system session local-repository))
384      (ignore-errors 
385        (#"newLocalRepositoryManager" 
386         repository-system local-repository))))))
387
388(defparameter *maven-http-proxy* nil
389  "A string containing the URI of an http proxy for Maven to use.")
390
391(defun make-proxy ()
392  "Return an aether.repository.Proxy instance initialized from *MAVEN-HTTP-PROXY*."
393  (unless *maven-http-proxy*
394    (warn "No proxy specified in *MAVEN-HTTP-PROXY*")
395    (return-from make-proxy nil))
396  (let* ((p (pathname *maven-http-proxy*))
397         (scheme (ext:url-pathname-scheme p))
398         (authority (ext:url-pathname-authority p))
399         (host (if (search ":" authority)
400                   (subseq authority 0 (search ":" authority))
401                   authority))
402         (port (when (search ":" authority)
403                 (parse-integer (subseq authority (1+ (search ":" authority))))))
404         ;; TODO allow specification of authentication
405         (authentication java:+null+))
406    (or 
407     (ignore-errors
408       (jss:new 'org.eclipse.aether.repository.Proxy
409                scheme host port authentication))
410     (ignore-errors
411       (jss:new 'org.sonatype.aether.repository.Proxy
412                scheme host port authentication)))))
413
414(defparameter *repository-system*  nil
415  "The aether.RepositorySystem used by the Maeven Aether connector.")
416(defun ensure-repository-system (&key (force nil))
417  (when (or force (not *repository-system*))
418    (setf *repository-system* (make-repository-system)))
419  *repository-system*)
420
421(defparameter *session* nil
422  "Reference to the Maven RepositorySystemSession")
423(defun ensure-session (&key (force nil))
424  "Ensure that the RepositorySystemSession has been created.
425
426If *MAVEN-HTTP-PROXY* is non-nil, parse its value as the http proxy."
427  (when (or force (not *session*))
428    (ensure-repository-system :force force)
429    (setf *session* (make-session *repository-system*))
430    (#"setRepositoryListener" *session* (make-repository-listener))
431    (when *maven-http-proxy*
432      (let ((proxy (make-proxy)))
433        (#"add" (#"getProxySelector" *session*)
434                proxy 
435                ;; A string specifying non proxy hosts, or null
436                java:+null+))))
437  *session*)
438
439(defun make-artifact (artifact-string)
440  "Return an instance of aether.artifact.DefaultArtifact initialized from ARTIFACT-STRING." 
441  (or
442   (ignore-errors
443     (jss:new 'aether.artifact.DefaultArtifact artifact-string))
444   (ignore-errors
445     (jss:new "org.sonatype.aether.util.artifact.DefaultArtifact" artifact-string))))
446
447(defun make-artifact-request () 
448  "Construct a new aether.resolution.ArtifactRequest."
449  (or 
450   (ignore-errors
451     (java:jnew (jss:find-java-class 'aether.resolution.ArtifactRequest)))
452   (ignore-errors
453     (java:jnew "org.sonatype.aether.resolution.ArtifactRequest"))))
454
455;;; TODO change this to work on artifact strings like log4j:log4j:jar:1.2.16
456(defun resolve-artifact (group-id artifact-id &key (version "LATEST" versionp))
457  "Resolve artifact to location on the local filesystem.
458
459Declared dependencies are not attempted to be located.
460
461If unspecified, the string \"LATEST\" will be used for the VERSION.
462
463Returns the Maven specific string for the artifact "
464  (unless versionp
465    (warn "Using LATEST for unspecified version."))
466  (unless *init* (init))
467  (let* ((artifact-string 
468          (format nil "~A:~A:~A" group-id artifact-id version))
469         (artifact 
470          (make-artifact artifact-string))
471         (artifact-request 
472          (make-artifact-request)))
473    (#"setArtifact" artifact-request artifact)
474    (#"addRepository" artifact-request (ensure-remote-repository))
475    (#"toString" (#"getFile" 
476                  (#"getArtifact" (#"resolveArtifact" (ensure-repository-system) 
477                                                      (ensure-session) artifact-request))))))
478
479(defun make-remote-repository (id type url) 
480  (or 
481   (ignore-errors 
482     (#"build" (jss:new "org.eclipse.aether.repository.RemoteRepository$Builder" id type url)))
483   (ignore-errors
484     (jss:new 'aether.repository.RemoteRepository id type url))))
485
486(defparameter *default-repository* 
487  "http://repo1.maven.org/maven2/")
488
489(defun add-repository (repository)
490  (ensure-remote-repository :repository repository))
491
492(defparameter *maven-remote-repository*  nil
493  "The remote repository used by the Maven Aether embedder.")
494(defun ensure-remote-repository (&key 
495                                   (force nil)
496                                   (repository *default-repository* repository-p))
497  (unless *init* (init))
498  (when (or force 
499            repository-p 
500            (not *maven-remote-repository*))
501    (let ((r (make-remote-repository "central" "default" repository)))
502      (when *maven-http-proxy*
503        (#"setProxy" r (make-proxy)))
504      (setf *maven-remote-repository* r)))
505  *maven-remote-repository*)
506
507(defun resolve-dependencies (group-id artifact-id 
508                             &key
509                               (version "LATEST" versionp)
510                               (repository *maven-remote-repository* repository-p))
511  "Dynamically resolve Maven dependencies for item with GROUP-ID and ARTIFACT-ID
512optionally with a VERSION and a REPOSITORY. 
513
514All recursive dependencies will be visited before resolution is successful.
515
516If unspecified, the string \"LATEST\" will be used for the VERSION.
517
518Returns a string containing the necessary jvm classpath entries packed
519in Java CLASSPATH representation."
520  (unless *init* (init))
521  (unless versionp
522    (warn "Using LATEST for unspecified version."))
523  (let* ((coords 
524          (format nil "~A:~A:~A" group-id artifact-id (if versionp version "LATEST")))
525         (artifact 
526          (make-artifact coords))
527         (dependency 
528          (java:jnew (jss:find-java-class 'aether.graph.Dependency)
529                     artifact (java:jfield (jss:find-java-class "JavaScopes") "COMPILE")))
530         (collect-request (java:jnew (jss:find-java-class "CollectRequest"))))
531    (#"setRoot" collect-request dependency)
532     ;; Don't call addRepository if we explicitly specify a NIL repository
533    (unless (and repository-p (not repository))
534      (#"addRepository" collect-request 
535                        (if repository-p
536                            (ensure-remote-repository :repository repository)
537                            (ensure-remote-repository))))
538    (let* ((node 
539            (#"getRoot" (#"collectDependencies" (ensure-repository-system) (ensure-session) collect-request)))
540           (dependency-request
541            ;;; pre Maven-3.3.x
542            #+nil
543            (java:jnew (jss:find-java-class "DependencyRequest")
544                       node java:+null+)
545            (jss:new 'DependencyRequest))
546           (nlg 
547            (java:jnew (jss:find-java-class "PreorderNodeListGenerator"))))
548      (#"setRoot" dependency-request node)
549      (#"resolveDependencies" (ensure-repository-system) (ensure-session) dependency-request)
550      (#"accept" node nlg)
551      (#"getClassPath" nlg))))
552
553(defun make-repository-listener ()
554  (flet ((log (e) 
555           (format cl:*load-verbose* "~&; abcl-asdf; ~A~%" (#"toString" e))))
556    (java:jinterface-implementation 
557     (#"getName" (jss:find-java-class 'aether.RepositoryListener))
558     "artifactDeployed" 
559     #'log
560     "artifactDeploying" 
561     #'log
562     "artifactDescriptorInvalid" 
563     #'log
564     "artifactDescriptorMissing" 
565     #'log
566     "artifactDownloaded" 
567     #'log
568     "artifactDownloading" 
569     #'log
570     "artifactInstalled" 
571     #'log
572     "artifactInstalling" 
573     #'log
574     "artifactResolved" 
575     #'log
576     "artifactResolving" 
577     #'log
578     "metadataDeployed" 
579     #'log
580     "metadataDeploying" 
581     #'log
582     "metadataDownloaded" 
583     #'log
584     "metadataDownloading" 
585     #'log
586     "metadataInstalled"
587     #'log
588     "metadataInstalling" 
589     #'log
590     "metadataInvalid" 
591     #'log
592     "metadataResolved" 
593     #'log
594     "metadataResolving"
595     #'log)))
596
597(defmethod resolve ((string string))
598  "Resolve a colon separated GROUP-ID:ARTIFACT-ID[:VERSION] reference to a Maven artifact.
599
600Examples of artifact references: \"log4j:log4j:1.2.14\" for
601'log4j-1.2.14.jar'.  Resolving \"log4j:log4j\" would return the latest
602version of the artifact known to the distributed Maven pom.xml graph.
603
604Returns a string containing the necessary classpath entries for this
605artifact and all of its transitive dependencies."
606  (let ((result (split-string string ":")))
607    (cond 
608      ((= (length result) 3)
609       (resolve-dependencies 
610        (first result) (second result) :version (third result)))
611      ((string= string "com.sun.jna:jna")
612       (warn "Replacing request for no longer available com.sun.jna:jna with net.java.dev.jna:jna")
613       (resolve-dependencies "net.java.dev.jna" "jna" :version "LATEST"))
614      ((= (length result) 2)
615       (resolve-dependencies
616        (first result) (second result)))
617      (t 
618       (destructuring-bind (group-id artifact-id &optional version repository)
619           (abcl-build:split-string string "/")
620         (setf result 
621               (apply #'resolve-dependencies group-id artifact-id
622                      (append (when version
623                                `(:version ,version))
624                              (when repository
625                                `(:repository ,repository))))))))))
626
627
628;;; Currently the last file listed in ASDF
629(provide 'abcl-asdf)
630
Note: See TracBrowser for help on using the repository browser.