gnu-maintenance: Optimize `latest-release'.
* guix/gnu-maintenance.scm (tarball-regexp, sans-extension, release-file): New procedures. (%alpha-tarball-rx): New variable. (releases): Use them instead of local copies. (latest-release): Rewrite to not do a recursive search of all versions and instead jump directly to the latest.
This commit is contained in:
		
							parent
							
								
									0fdd3bea58
								
							
						
					
					
						commit
						cac137aa84
					
				
					 1 changed files with 58 additions and 29 deletions
				
			
		|  | @ -252,30 +252,34 @@ stored." | ||||||
|     (_ |     (_ | ||||||
|      (values "ftp.gnu.org" (string-append "/gnu/" project))))) |      (values "ftp.gnu.org" (string-append "/gnu/" project))))) | ||||||
| 
 | 
 | ||||||
|  | (define tarball-regexp | ||||||
|  |   (memoize | ||||||
|  |    (lambda (project) | ||||||
|  |      "Return a regexp matching tarball names for PROJECT." | ||||||
|  |      (make-regexp (string-append "^" project | ||||||
|  |                                  "-([0-9]|[^-])*(-src)?\\.tar\\."))))) | ||||||
|  | 
 | ||||||
|  | (define %alpha-tarball-rx | ||||||
|  |   (make-regexp "^.*-.*[0-9](-|~)?(alpha|beta|rc|cvs|svn|git)-?[0-9\\.]*\\.tar\\.")) | ||||||
|  | 
 | ||||||
|  | (define (sans-extension tarball) | ||||||
|  |   "Return TARBALL without its .tar.* extension." | ||||||
|  |   (let ((end (string-contains tarball ".tar"))) | ||||||
|  |     (substring tarball 0 end))) | ||||||
|  | 
 | ||||||
|  | (define (release-file project file) | ||||||
|  |   "Return #f if FILE is not a release tarball of PROJECT, otherwise return | ||||||
|  | PACKAGE-VERSION." | ||||||
|  |   (and (not (string-suffix? ".sig" file)) | ||||||
|  |        (regexp-exec (tarball-regexp project) file) | ||||||
|  |        (not (regexp-exec %alpha-tarball-rx file)) | ||||||
|  |        (let ((s (sans-extension file))) | ||||||
|  |          (and (regexp-exec %package-name-rx s) s)))) | ||||||
|  | 
 | ||||||
| (define (releases project) | (define (releases project) | ||||||
|   "Return the list of releases of PROJECT as a list of release name/directory |   "Return the list of releases of PROJECT as a list of release name/directory | ||||||
| pairs.  Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\"). " | pairs.  Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\"). " | ||||||
|   ;; TODO: Parse something like fencepost.gnu.org:/gd/gnuorg/packages-ftp. |   ;; TODO: Parse something like fencepost.gnu.org:/gd/gnuorg/packages-ftp. | ||||||
|   (define release-rx |  | ||||||
|     (make-regexp (string-append "^" project |  | ||||||
|                                 "-([0-9]|[^-])*(-src)?\\.tar\\."))) |  | ||||||
| 
 |  | ||||||
|   (define alpha-rx |  | ||||||
|     (make-regexp "^.*-.*[0-9](-|~)?(alpha|beta|rc|cvs|svn|git)-?[0-9\\.]*\\.tar\\.")) |  | ||||||
| 
 |  | ||||||
|   (define (sans-extension tarball) |  | ||||||
|     (let ((end (string-contains tarball ".tar"))) |  | ||||||
|       (substring tarball 0 end))) |  | ||||||
| 
 |  | ||||||
|   (define (release-file file) |  | ||||||
|     ;; Return #f if FILE is not a release tarball, otherwise return |  | ||||||
|     ;; PACKAGE-VERSION. |  | ||||||
|     (and (not (string-suffix? ".sig" file)) |  | ||||||
|          (regexp-exec release-rx file) |  | ||||||
|          (not (regexp-exec alpha-rx file)) |  | ||||||
|          (let ((s (sans-extension file))) |  | ||||||
|            (and (regexp-exec %package-name-rx s) s)))) |  | ||||||
| 
 |  | ||||||
|   (let-values (((server directory) (ftp-server/directory project))) |   (let-values (((server directory) (ftp-server/directory project))) | ||||||
|     (define conn (ftp-open server)) |     (define conn (ftp-open server)) | ||||||
| 
 | 
 | ||||||
|  | @ -301,7 +305,7 @@ pairs.  Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\"). | ||||||
|                   ;; guile-www; in mit-scheme, filter out binaries. |                   ;; guile-www; in mit-scheme, filter out binaries. | ||||||
|                   (filter-map (match-lambda |                   (filter-map (match-lambda | ||||||
|                                 ((file 'file . _) |                                 ((file 'file . _) | ||||||
|                                  (and=> (release-file file) |                                  (and=> (release-file project file) | ||||||
|                                         (cut cons <> directory))) |                                         (cut cons <> directory))) | ||||||
|                                 (_ #f)) |                                 (_ #f)) | ||||||
|                               files) |                               files) | ||||||
|  | @ -309,14 +313,39 @@ pairs.  Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\"). | ||||||
| 
 | 
 | ||||||
| (define (latest-release project) | (define (latest-release project) | ||||||
|   "Return (\"FOO-X.Y\" . \"/bar/foo\") or #f." |   "Return (\"FOO-X.Y\" . \"/bar/foo\") or #f." | ||||||
|   (let ((releases (releases project))) |   (define (latest a b) | ||||||
|     (and (not (null? releases)) |     (if (version>? a b) a b)) | ||||||
|          (fold (lambda (release latest) | 
 | ||||||
|                  (if (version>? (car release) (car latest)) |   (define contains-digit? | ||||||
|                      release |     (cut string-any char-set:digit <>)) | ||||||
|                      latest)) | 
 | ||||||
|                '("" . "") |   (let-values (((server directory) (ftp-server/directory project))) | ||||||
|                releases)))) |     (define conn (ftp-open server)) | ||||||
|  | 
 | ||||||
|  |     (let loop ((directory directory)) | ||||||
|  |       (let* ((entries (ftp-list conn directory)) | ||||||
|  |              (subdirs (filter-map (match-lambda | ||||||
|  |                                    ((dir 'directory . _) dir) | ||||||
|  |                                    (_ #f)) | ||||||
|  |                                   entries))) | ||||||
|  |         (match subdirs | ||||||
|  |           (() | ||||||
|  |            ;; No sub-directories, so assume that tarballs are here. | ||||||
|  |            (let ((files (filter-map (match-lambda | ||||||
|  |                                      ((file 'file . _) | ||||||
|  |                                       (release-file project file)) | ||||||
|  |                                      (_ #f)) | ||||||
|  |                                     entries))) | ||||||
|  |              (and=> (reduce latest #f files) | ||||||
|  |                     (cut cons <> directory)))) | ||||||
|  |           ((subdirs ...) | ||||||
|  |            ;; Assume that SUBDIRS correspond to versions, and jump into the | ||||||
|  |            ;; one with the highest version number.  Filter out sub-directories | ||||||
|  |            ;; that do not contain digits---e.g., /gnuzilla/lang. | ||||||
|  |            (let* ((subdirs (filter contains-digit? subdirs)) | ||||||
|  |                   (target  (reduce latest #f subdirs))) | ||||||
|  |              (and target | ||||||
|  |                   (loop (string-append directory "/" target)))))))))) | ||||||
| 
 | 
 | ||||||
| (define %package-name-rx | (define %package-name-rx | ||||||
|   ;; Regexp for a package name, e.g., "foo-X.Y".  Since TeXmacs uses |   ;; Regexp for a package name, e.g., "foo-X.Y".  Since TeXmacs uses | ||||||
|  |  | ||||||
		Reference in a new issue