import: launchpad: Handle list of source URLs correctly.
[jackhill/guix/guix.git] / guix / import / launchpad.scm
CommitLineData
ae031d45 1;;; GNU Guix --- Functional package management for GNU
8b9b5a7f 2;;; Copyright © 2019, 2020 Arun Isaac <arunisaac@systemreboot.net>
ae031d45
AI
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix import launchpad)
20 #:use-module (ice-9 match)
21 #:use-module (srfi srfi-1)
22 #:use-module (srfi srfi-26)
23 #:use-module (web uri)
24 #:use-module ((guix download) #:prefix download:)
25 #:use-module (guix import json)
26 #:use-module (guix packages)
27 #:use-module (guix upstream)
28 #:use-module (guix utils)
29 #:export (%launchpad-updater))
30
31(define (find-extension url)
32 "Return the extension of the archive e.g. '.tar.gz' given a URL, or
33false if none is recognized"
34 (find (lambda (x) (string-suffix? x url))
35 (list ".tar.gz" ".tar.bz2" ".tar.xz"
36 ".zip" ".tar" ".tgz" ".tbz" ".love")))
37
38(define (updated-launchpad-url old-package new-version)
39 ;; Return a url for the OLD-PACKAGE with NEW-VERSION. If no source url in
40 ;; the OLD-PACKAGE is a Launchpad url, then return false.
41
42 (define (updated-url url)
43 (and (string-prefix? "https://launchpad.net/" url)
44 (let ((ext (or (find-extension url) ""))
45 (name (package-name old-package))
46 (version (package-version old-package))
47 (repo (launchpad-repository url)))
48 (cond
49 ((and
50 (>= (length (string-split version #\.)) 2)
51 (string=? (string-append "https://launchpad.net/"
52 repo "/" (version-major+minor version)
53 "/" version "/+download/" repo "-" version ext)
54 url))
55 (string-append "https://launchpad.net/"
56 repo "/" (version-major+minor new-version)
57 "/" new-version "/+download/" repo "-" new-version ext))
58 (#t #f))))) ; Some URLs are not recognised.
59
f54cbc0e
LC
60 (match (package-source old-package)
61 ((? origin? origin)
62 (let ((source-uri (origin-uri origin))
63 (fetch-method (origin-method origin)))
64 (and (eq? fetch-method download:url-fetch)
65 (match source-uri
66 ((? string?)
67 (updated-url source-uri))
68 ((source-uri ...)
8b9b5a7f 69 (any updated-url source-uri))))))
f54cbc0e 70 (_ #f)))
ae031d45
AI
71
72(define (launchpad-package? package)
73 "Return true if PACKAGE is a package from Launchpad, else false."
74 (->bool (updated-launchpad-url package "1.0.0")))
75
76(define (launchpad-repository url)
77 "Return a string e.g. linuxdcpp of the name of the repository, from a string
78URL of the form
79'https://launchpad.net/linuxdcpp/1.1/1.1.0/+download/linuxdcpp-1.1.0.tar.bz2'"
80 (match (string-split (uri-path (string->uri url)) #\/)
81 ((_ repo . rest) repo)))
82
83(define (latest-released-version package-name)
84 "Return a string of the newest released version name given the PACKAGE-NAME,
85for example, 'linuxdcpp'. Return #f if there is no releases."
86 (define (pre-release? x)
87 ;; Versions containing anything other than digit characters and "." (for
88 ;; example, "5.1.0-rc1") are assumed to be pre-releases.
89 (not (string-every (char-set-union (char-set #\.)
90 char-set:digit)
81c3dc32 91 (assoc-ref x "version"))))
ae031d45 92
81c3dc32 93 (assoc-ref
ae031d45
AI
94 (last (remove
95 pre-release?
81c3dc32
LC
96 (vector->list
97 (assoc-ref (json-fetch
98 (string-append "https://api.launchpad.net/1.0/"
99 package-name "/releases"))
100 "entries"))))
ae031d45
AI
101 "version"))
102
103(define (latest-release pkg)
104 "Return an <upstream-source> for the latest release of PKG."
105 (define (origin-github-uri origin)
106 (match (origin-uri origin)
107 ((? string? url) url) ; surely a Launchpad URL
108 ((urls ...)
109 (find (cut string-contains <> "launchpad.net") urls))))
110
111 (let* ((source-uri (origin-github-uri (package-source pkg)))
112 (name (package-name pkg))
113 (newest-version (latest-released-version name)))
114 (if newest-version
115 (upstream-source
116 (package name)
117 (version newest-version)
118 (urls (list (updated-launchpad-url pkg newest-version))))
119 #f))) ; On Launchpad but no proper releases
120
121(define %launchpad-updater
122 (upstream-updater
123 (name 'launchpad)
124 (description "Updater for Launchpad packages")
125 (pred launchpad-package?)
126 (latest latest-release)))