summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2017-05-18 16:21:35 +0200
committerLudovic Courtès <ludo@gnu.org>2017-05-18 16:24:02 +0200
commit920803fbf443f7e40ed299f433255f10a4ae9fb3 (patch)
treefa7efbcbdadee16fd75a57b6f2164df3dbb6359c
parent266d281d253ffd20336f837fc64a64a14eb44b12 (diff)
maint: Add 'update-NEWS' target.
* build-aux/update-NEWS.scm: New file. * Makefile.am (EXTRA_DIST): Add it. (GUIX_MAINTENANCE_DIRECTORY): New variable. (update-NEWS): New target. (.PHONY): Add it.
-rw-r--r--Makefile.am12
-rw-r--r--build-aux/update-NEWS.scm161
2 files changed, 172 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 5bfc9ca88c6..e1c7cdd7fa9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -420,6 +420,7 @@ EXTRA_DIST = \
420 build-aux/generate-authors.scm \ 420 build-aux/generate-authors.scm \
421 build-aux/test-driver.scm \ 421 build-aux/test-driver.scm \
422 build-aux/update-guix-package.scm \ 422 build-aux/update-guix-package.scm \
423 build-aux/update-NEWS.scm \
423 build-aux/run-system-tests.scm \ 424 build-aux/run-system-tests.scm \
424 d3.v3.js \ 425 d3.v3.js \
425 graph.js \ 426 graph.js \
@@ -641,6 +642,15 @@ update-guix-package:
641 $(top_srcdir)/build-aux/update-guix-package.scm \ 642 $(top_srcdir)/build-aux/update-guix-package.scm \
642 "`git rev-parse HEAD`" 643 "`git rev-parse HEAD`"
643 644
645# Location of a checkout of <git://git.savannah.gnu.org/guix/maintenance.git>.
646# Package data from this checkout is used by 'update-NEWS.scm'.
647GUIX_MAINTENANCE_DIRECTORY ?= $(top_srcdir)/../guix-maintenance
648
649update-NEWS: $(GOBJECTS)
650 $(top_builddir)/pre-inst-env "$(GUILE)" \
651 $(top_srcdir)/build-aux/update-NEWS.scm \
652 $(top_srcdir)/NEWS "$(GUIX_MAINTENANCE_DIRECTORY)/data"
653
644# Make sure we're not shipping a file that embeds a local /gnu/store file name. 654# Make sure we're not shipping a file that embeds a local /gnu/store file name.
645assert-no-store-file-names: $(distdir)/ChangeLog 655assert-no-store-file-names: $(distdir)/ChangeLog
646 $(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \ 656 $(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \
@@ -676,7 +686,7 @@ hydra-jobs.scm: $(GOBJECTS)
676.PHONY: assert-no-store-file-names assert-binaries-available 686.PHONY: assert-no-store-file-names assert-binaries-available
677.PHONY: assert-final-inputs-self-contained 687.PHONY: assert-final-inputs-self-contained
678.PHONY: clean-go make-go 688.PHONY: clean-go make-go
679.PHONY: update-guix-package release 689.PHONY: update-guix-package update-NEWS release
680 690
681## -------------- ## 691## -------------- ##
682## Silent rules. ## 692## Silent rules. ##
diff --git a/build-aux/update-NEWS.scm b/build-aux/update-NEWS.scm
new file mode 100644
index 00000000000..2e8f68c9a8e
--- /dev/null
+++ b/build-aux/update-NEWS.scm
@@ -0,0 +1,161 @@
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2017 Ludovic Courtès <ludo@gnu.org>
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;;; Commentary:
20;;;
21;;; This script updates the list of new and updated packages in 'NEWS'.
22;;;
23;;; Code:
24
25(use-modules (gnu) (guix)
26 (guix build utils)
27 ((guix ui) #:select (fill-paragraph))
28 (srfi srfi-1)
29 (srfi srfi-11)
30 (ice-9 match)
31 (ice-9 rdelim)
32 (ice-9 regex)
33 (ice-9 pretty-print))
34
35(define %header-rx
36 (make-regexp "^\\* Changes in (version )?([0-9.]+) \\(since ([0-9.]+)\\)"))
37
38(define (NEWS->versions port)
39 "Return two values: the previous version and the current version as read
40from PORT, which is an input port on the 'NEWS' file."
41 (let loop ()
42 (let ((line (read-line port)))
43 (cond ((eof-object? line)
44 (error "failed to determine previous and current version"
45 port))
46 ((regexp-exec %header-rx line)
47 =>
48 (lambda (match)
49 (values (match:substring match 3)
50 (match:substring match 2))))
51 (else
52 (loop))))))
53
54(define (skip-to-org-heading port)
55 "Read from PORT until an Org heading is found."
56 (let loop ()
57 (let ((next (peek-char port)))
58 (cond ((eqv? next #\*)
59 #t)
60 ((eof-object? next)
61 (error "next heading could not be found"))
62 (else
63 (read-line port)
64 (loop))))))
65
66(define (rewrite-org-section input output heading-rx proc)
67 "Write to OUTPUT the text read from INPUT, but with the first Org section
68matching HEADING-RX replaced by NEW-HEADING and CONTENTS."
69 (let loop ()
70 (let ((line (read-line input)))
71 (cond ((eof-object? line)
72 (error "failed to match heading regexp" heading-rx))
73 ((regexp-exec heading-rx line)
74 =>
75 (lambda (match)
76 (proc match output)
77 (skip-to-org-heading input)
78 (dump-port input output)
79 #t))
80 (else
81 (display line output)
82 (newline output)
83 (loop))))))
84
85(define (enumeration->paragraph lst)
86 "Turn LST, a list of strings, into a single string that is a ready-to-print
87paragraph."
88 (fill-paragraph (string-join (sort lst string<?) ", ")
89 75))
90
91(define (write-packages-added news-file old new)
92 "Write to NEWS-FILE the list of packages added between OLD and NEW."
93 (let ((added (lset-difference string=? (map car new) (map car old))))
94 (with-atomic-file-replacement news-file
95 (lambda (input output)
96 (rewrite-org-section input output
97 (make-regexp "^(\\*+) (.*) new packages")
98 (lambda (match port)
99 (let ((stars (match:substring match 1)))
100 (format port
101 "~a ~a new packages~%~%~a~%~%"
102 stars (length added)
103 (enumeration->paragraph added)))))))))
104
105(define (write-packages-updates news-file old new)
106 "Write to NEWS-FILE the list of packages upgraded between OLD and NEW."
107 (let ((upgraded (filter-map (match-lambda
108 ((package . new-version)
109 (match (assoc package old)
110 ((_ . old-version)
111 (and (version>? new-version old-version)
112 (string-append package "@"
113 new-version)))
114 (_ #f))))
115 new)))
116 (with-atomic-file-replacement news-file
117 (lambda (input output)
118 (rewrite-org-section input output
119 (make-regexp "^(\\*+) (.*) package updates")
120 (lambda (match port)
121 (let ((stars (match:substring match 1)))
122 (format port
123 "~a ~a package updates~%~%~a~%~%"
124 stars (length upgraded)
125 (enumeration->paragraph upgraded)))))))))
126
127
128(define (main . args)
129 (match args
130 ((news-file data-directory)
131 ;; Don't browse things listed in the user's $GUIX_PACKAGE_PATH. Here we
132 ;; assume that the last item in (%package-module-path) is the distro
133 ;; directory.
134 (parameterize ((%package-module-path
135 (list (last (%package-module-path)))))
136 (define (package-file version)
137 (string-append data-directory "/packages-"
138 version ".txt"))
139
140 (let-values (((previous-version new-version)
141 (call-with-input-file news-file NEWS->versions)))
142 (let* ((old (call-with-input-file (package-file previous-version)
143 read))
144 (new (fold-packages (lambda (p r)
145 (alist-cons (package-name p) (package-version p)
146 r))
147 '())))
148 (call-with-output-file (package-file new-version)
149 (lambda (port)
150 (pretty-print new port)))
151
152 (write-packages-added news-file old new)
153 (write-packages-updates news-file old new)))))
154 (x
155 (format (current-error-port) "Usage: update-NEWS NEWS-FILE DATA-DIRECTORY
156
157Update the list of new and updated packages in NEWS-FILE using the
158previous-version package list from DATA-DIRECTORY.\n")
159 (exit 1))))
160
161(apply main (cdr (command-line)))