summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi9
-rw-r--r--guix/import/cran.scm82
-rw-r--r--guix/scripts/refresh.scm4
3 files changed, 77 insertions, 18 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 6f26568a7a..99c10d8dc7 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -4270,14 +4270,17 @@ may be one of:
 @item gnu
 the updater for GNU packages;
 @item elpa
-the updater for @uref{http://elpa.gnu.org/, ELPA} packages.
+the updater for @uref{http://elpa.gnu.org/, ELPA} packages;
+@item cran
+the updater fro @uref{http://cran.r-project.org/, CRAN} packages.
 @end table
 
 For instance, the following commands only checks for updates of Emacs
-packages hosted at @code{elpa.gnu.org}:
+packages hosted at @code{elpa.gnu.org} and updates of CRAN packages:
 
 @example
-$ guix refresh -t elpa
+$ guix refresh -t elpa -t cran
+gnu/packages/statistics.scm:819:13: r-testthat would be upgraded from 0.10.0 to 0.11.0
 gnu/packages/emacs.scm:856:13: emacs-auctex would be upgraded from 11.88.6 to 11.88.9
 @end example
 
diff --git a/guix/import/cran.scm b/guix/import/cran.scm
index 585cb9fec2..218d55787a 100644
--- a/guix/import/cran.scm
+++ b/guix/import/cran.scm
@@ -20,6 +20,7 @@
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
   #:use-module (sxml simple)
   #:use-module (sxml match)
   #:use-module (sxml xpath)
@@ -29,7 +30,10 @@
   #:use-module (guix base32)
   #:use-module ((guix download) #:select (download-to-store))
   #:use-module (guix import utils)
-  #:export (cran->guix-package))
+  #:use-module (guix upstream)
+  #:use-module (guix packages)
+  #:export (cran->guix-package
+            %cran-updater))
 
 ;;; Commentary:
 ;;;
@@ -108,12 +112,25 @@ or #f on failure.  NAME is case-sensitive."
                              name)
                      (symbol->string name))))))))
 
+(define (downloads->url downloads)
+  "Extract from DOWNLOADS, the downloads item of the CRAN sxml tree, the
+download URL."
+  (string-append "mirror://cran/"
+                 ;; Remove double dots, because we want an
+                 ;; absolute path.
+                 (regexp-substitute/global
+                  #f "\\.\\./"
+                  (string-join ((sxpath '((xhtml:a 1) @ href *text*))
+                                (table-datum downloads " Package source: ")))
+                  'pre 'post)))
+
+(define (nodes->text nodeset)
+  "Return the concatenation of the text nodes among NODESET."
+  (string-join ((sxpath '(// *text*)) nodeset) " "))
+
 (define (cran-sxml->sexp sxml)
   "Return the `package' s-expression for a CRAN package from the SXML
 representation of the package page."
-  (define (nodes->text nodeset)
-    (string-join ((sxpath '(// *text*)) nodeset) " "))
-
   (define (guix-name name)
     (if (string-prefix? "r-" name)
         (string-downcase name)
@@ -136,16 +153,7 @@ representation of the package page."
                        (table-datum summary "License:")))
           (home-page  (nodes->text ((sxpath '((xhtml:a 1)))
                                     (table-datum summary "URL:"))))
-          (source-url (string-append "mirror://cran/"
-                                     ;; Remove double dots, because we want an
-                                     ;; absolute path.
-                                     (regexp-substitute/global
-                                      #f "\\.\\./"
-                                      (string-join
-                                       ((sxpath '((xhtml:a 1) @ href *text*))
-                                        (table-datum downloads
-                                                     " Package source: ")))
-                                      'pre 'post)))
+          (source-url (downloads->url downloads))
           (tarball    (with-store store (download-to-store store source-url)))
           (sysdepends (map match:substring
                            (list-matches
@@ -186,3 +194,49 @@ representation of the package page."
 `package' s-expression corresponding to that package, or #f on failure."
   (let ((module-meta (cran-fetch package-name)))
     (and=> module-meta cran-sxml->sexp)))
+
+
+;;;
+;;; Updater.
+;;;
+
+(define (latest-release package)
+  "Return an <upstream-source> for the latest release of PACKAGE."
+  (define name
+    (if (string-prefix? "r-" package)
+        (string-drop package 2)
+        package))
+
+  (define sxml
+    (cran-fetch name))
+
+  (and sxml
+       (sxml-match-let*
+        (((*TOP* (xhtml:html
+                  ,head
+                  (xhtml:body
+                   (xhtml:h2 ,name-and-synopsis)
+                   (xhtml:p ,description)
+                   ,summary
+                   (xhtml:h4 "Downloads:") ,downloads
+                   . ,rest)))
+          sxml))
+        (let ((version (nodes->text (table-datum summary "Version:")))
+              (url     (downloads->url downloads)))
+          ;; CRAN does not provide signatures.
+          (upstream-source
+           (package package)
+           (version version)
+           (urls (list url)))))))
+
+(define (cran-package? package)
+  "Return true if PACKAGE is an R package from CRAN."
+  ;; Assume all R packages are available on CRAN.
+  (string-prefix? "r-" (package-name package)))
+
+(define %cran-updater
+  (upstream-updater 'cran
+                    cran-package?
+                    latest-release))
+
+;;; cran.scm ends here
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index 99fdc2ca65..6f7ca4a41b 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -28,6 +28,7 @@
   #:use-module (guix upstream)
   #:use-module ((guix gnu-maintenance) #:select (%gnu-updater))
   #:use-module (guix import elpa)
+  #:use-module (guix import cran)
   #:use-module (guix gnupg)
   #:use-module (gnu packages)
   #:use-module ((gnu packages commencement) #:select (%final-inputs))
@@ -139,7 +140,8 @@ specified with `--select'.\n"))
 (define %updaters
   ;; List of "updaters" used by default.  They are consulted in this order.
   (list %gnu-updater
-        %elpa-updater))
+        %elpa-updater
+        %cran-updater))
 
 (define (lookup-updater name)
   "Return the updater called NAME."