gnu: youtube-dl: Update to 2015.06.25.
[jackhill/guix/guix.git] / gnu / packages.scm
index 6ef0fb6..6e46a89 100644 (file)
@@ -51,7 +51,8 @@
 
             check-package-freshness
 
-            specification->package))
+            specification->package
+            specification->package+output))
 
 ;;; Commentary:
 ;;;
@@ -211,14 +212,18 @@ same package twice."
   (let ((packages (delay
                     (fold-packages (lambda (p r)
                                      (vhash-cons (package-name p) p r))
-                                   vlist-null))))
+                                   vlist-null)))
+        (version>? (lambda (p1 p2)
+                     (version>? (package-version p1) (package-version p2)))))
     (lambda* (name #:optional version)
       "Return the list of packages with the given NAME.  If VERSION is not #f,
-then only return packages whose version is equal to VERSION."
-      (let ((matching (vhash-fold* cons '() name (force packages))))
+then only return packages whose version is prefixed by VERSION, sorted in
+decreasing version order."
+      (let ((matching (sort (vhash-fold* cons '() name (force packages))
+                            version>?)))
         (if version
             (filter (lambda (package)
-                      (string=? (package-version package) version))
+                      (string-prefix? version (package-version package)))
                     matching)
             matching)))))
 
@@ -414,3 +419,36 @@ present, return the preferred newest version."
            (leave (_ "~A: package not found for version ~a~%")
                   name version)
            (leave (_ "~A: unknown package~%") name))))))
+
+(define* (specification->package+output spec #:optional (output "out"))
+  "Return the package and output specified by SPEC, or #f and #f; SPEC may
+optionally contain a version number and an output name, as in these examples:
+
+  guile
+  guile-2.0.9
+  guile:debug
+  guile-2.0.9:debug
+
+If SPEC does not specify a version number, return the preferred newest
+version; if SPEC does not specify an output, return OUTPUT."
+  (define (ensure-output p sub-drv)
+    (if (member sub-drv (package-outputs p))
+        sub-drv
+        (leave (_ "package `~a' lacks output `~a'~%")
+               (package-full-name p)
+               sub-drv)))
+
+  (let-values (((name version sub-drv)
+                (package-specification->name+version+output spec output)))
+    (match (find-best-packages-by-name name version)
+      ((p)
+       (values p (ensure-output p sub-drv)))
+      ((p p* ...)
+       (warning (_ "ambiguous package specification `~a'~%")
+                spec)
+       (warning (_ "choosing ~a from ~a~%")
+                (package-full-name p)
+                (location->string (package-location p)))
+       (values p (ensure-output p sub-drv)))
+      (()
+       (leave (_ "~a: package not found~%") spec)))))