From 873f6f1334ab06a69e768a8aea0054404237542f Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 14 Sep 2019 17:54:06 +0200 Subject: git: Add 'commit-difference'. * guix/git.scm (commit-closure, commit-difference): New procedures. * guix/tests/git.scm, tests/git.scm: New files. * Makefile.am (dist_noinst_DATA): Add guix/tests/git.scm. (SCM_TESTS): Add tests/git.scm. --- guix/tests/git.scm | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 guix/tests/git.scm (limited to 'guix/tests/git.scm') diff --git a/guix/tests/git.scm b/guix/tests/git.scm new file mode 100644 index 0000000000..52abe77c83 --- /dev/null +++ b/guix/tests/git.scm @@ -0,0 +1,97 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2019 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix tests git) + #:use-module (git) + #:use-module (guix utils) + #:use-module (guix build utils) + #:use-module (ice-9 match) + #:use-module (ice-9 control) + #:export (git-command + with-temporary-git-repository + find-commit)) + +(define git-command + (make-parameter "git")) + +(define (populate-git-repository directory directives) + "Initialize a new Git checkout and repository in DIRECTORY and apply +DIRECTIVES. Each element of DIRECTIVES is an sexp like: + + (add \"foo.txt\" \"hi!\") + +Return DIRECTORY on success." + + ;; Note: As of version 0.2.0, Guile-Git lacks the necessary bindings to do + ;; all this, so resort to the "git" command. + (define (git command . args) + (apply invoke (git-command) "-C" directory + command args)) + + (mkdir-p directory) + (git "init") + + (let loop ((directives directives)) + (match directives + (() + directory) + ((('add file contents) rest ...) + (let ((file (string-append directory "/" file))) + (mkdir-p (dirname file)) + (call-with-output-file file + (lambda (port) + (display contents port))) + (git "add" file) + (loop rest))) + ((('commit text) rest ...) + (git "commit" "-m" text) + (loop rest)) + ((('branch name) rest ...) + (git "branch" name) + (loop rest)) + ((('checkout branch) rest ...) + (git "checkout" branch) + (loop rest)) + ((('merge branch message) rest ...) + (git "merge" branch "-m" message) + (loop rest))))) + +(define (call-with-temporary-git-repository directives proc) + (call-with-temporary-directory + (lambda (directory) + (populate-git-repository directory directives) + (proc directory)))) + +(define-syntax-rule (with-temporary-git-repository directory + directives exp ...) + "Evaluate EXP in a context where DIRECTORY contains a checkout populated as +per DIRECTIVES." + (call-with-temporary-git-repository directives + (lambda (directory) + exp ...))) + +(define (find-commit repository message) + "Return the commit in REPOSITORY whose message includes MESSAGE, a string." + (let/ec return + (fold-commits (lambda (commit _) + (and (string-contains (commit-message commit) + message) + (return commit))) + #f + repository) + (error "commit not found" message))) -- cgit v1.2.3 From 8ba7fd3cd6962f1c1aaaa5f71eed7f9222094f25 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 14 Sep 2019 23:16:54 +0200 Subject: channels: Add support for a news file. * guix/channels.scm ()[news-file]: New field. (read-channel-metadata): Set the 'news-file' field. (read-channel-metadata-from-source): Likewise. (, ): New record types. (sexp->channel-news-entry, read-channel-news) (channel-news-for-commit): New procedures. * guix/tests/git.scm (populate-git-repository): For 'add', allow CONTENTS to be a procedure. * tests/channels.scm ("channel-news, no news") ("channel-news, one entry"): New tests. * doc/guix.texi (Channels): Document it. --- doc/guix.texi | 62 +++++++++++++++++++++++++++ guix/channels.scm | 123 +++++++++++++++++++++++++++++++++++++++++++++++++---- guix/tests/git.scm | 7 ++- tests/channels.scm | 99 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+), 9 deletions(-) (limited to 'guix/tests/git.scm') diff --git a/doc/guix.texi b/doc/guix.texi index af1903f6ff..cd108faa8f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -3991,6 +3991,68 @@ add a meta-data file @file{.guix-channel} that contains: (directory "guix")) @end lisp +@cindex news, for channels +@subsection Writing Channel News + +Channel authors may occasionally want to communicate to their users +information about important changes in the channel. You'd send them all +an email, but that's not convenient. + +Instead, channels can provide a @dfn{news file}; when the channel users +run @command{guix pull}, that news file is automatically read and +@command{guix pull --news} can display the announcements that correspond +to the new commits that have been pulled, if any. + +To do that, channel authors must first declare the name of the news file +in their @file{.guix-channel} file: + +@lisp +(channel + (version 0) + (news-file "etc/news.txt")) +@end lisp + +The news file itself, @file{etc/news.txt} in this example, must look +something like this: + +@lisp +(channel-news + (version 0) + (entry (commit "d894ab8e9bfabcefa6c49d9ba2e834dd5a73a300") + (title (en "Fixed terrible bug") + (fr "Oh la la")) + (body (en "@@emph@{Good news@}! It's fixed!") + (eo "Certe ĝi pli bone funkcias nun!"))) + (entry (commit "bdcabe815cd28144a2d2b4bc3c5057b051fa9906") + (title (en "Added a great package") + (ca "Què vol dir guix?")) + (body (en "Don't miss the @@code@{hello@} package!")))) +@end lisp + +The file consists of a list of @dfn{news entries}. Each entry is +associated with a commit: it describes changes made in this commit, +possibly in preceding commits as well. Users see entries only the first +time they obtain the commit the entry refers to. + +The @code{title} field should be a one-line summary while @code{body} +can be arbitrarily long, and both can contain Texinfo markup +(@pxref{Overview,,, texinfo, GNU Texinfo}). Both the title and body are +a list of language tag/message tuples, which allows @command{guix pull} +to display news in the language that corresponds to the user's locale. + +If you want to translate news using a gettext-based workflow, you can +extract translatable strings with @command{xgettext} (@pxref{xgettext +Invocation,,, gettext, GNU Gettext Utilities}). For example, assuming +you write news entries in English first, the command below creates a PO +file containing the strings to translate: + +@example +xgettext -o news.po -l scheme -ken etc/news.scm +@end example + +To sum up, yes, you could use your channel as a blog. But beware, this +is @emph{not quite} what your users might expect. + @subsection Replicating Guix @cindex pinning, channels diff --git a/guix/channels.scm b/guix/channels.scm index ebb2cacbc7..0dadba616f 100644 --- a/guix/channels.scm +++ b/guix/channels.scm @@ -19,6 +19,7 @@ ;;; along with GNU Guix. If not, see . (define-module (guix channels) + #:use-module (git) #:use-module (guix git) #:use-module (guix records) #:use-module (guix gexp) @@ -29,6 +30,7 @@ #:use-module (guix derivations) #:use-module (guix combinators) #:use-module (guix diagnostics) + #:use-module (guix sets) #:use-module (guix store) #:use-module (guix i18n) #:use-module ((guix utils) @@ -67,7 +69,14 @@ %channel-profile-hooks channel-instances->derivation - profile-channels)) + profile-channels + + channel-news-entry? + channel-news-entry-commit + channel-news-entry-title + channel-news-entry-body + + channel-news-for-commit)) ;;; Commentary: ;;; @@ -110,10 +119,11 @@ (checkout channel-instance-checkout)) (define-record-type - (channel-metadata directory dependencies) + (channel-metadata directory dependencies news-file) channel-metadata? (directory channel-metadata-directory) ;string with leading slash - (dependencies channel-metadata-dependencies)) ;list of + (dependencies channel-metadata-dependencies) ;list of + (news-file channel-metadata-news-file)) ;string | #f (define (channel-reference channel) "Return the \"reference\" for CHANNEL, an sexp suitable for @@ -129,12 +139,13 @@ if valid metadata could not be read from PORT." (match (read port) (('channel ('version 0) properties ...) (let ((directory (and=> (assoc-ref properties 'directory) first)) - (dependencies (or (assoc-ref properties 'dependencies) '()))) + (dependencies (or (assoc-ref properties 'dependencies) '())) + (news-file (and=> (assoc-ref properties 'news-file) first))) (channel-metadata - (cond ((not directory) "/") + (cond ((not directory) "/") ;directory ((string-prefix? "/" directory) directory) (else (string-append "/" directory))) - (map (lambda (item) + (map (lambda (item) ;dependencies (let ((get (lambda* (key #:optional default) (or (and=> (assoc-ref item key) first) default)))) (and-let* ((name (get 'name)) @@ -145,7 +156,8 @@ if valid metadata could not be read from PORT." (branch branch) (url url) (commit (get 'commit)))))) - dependencies)))) + dependencies) + news-file))) ;news-file ((and ('channel ('version version) _ ...) sexp) (raise (condition (&message (message "unsupported '.guix-channel' version")) @@ -169,7 +181,7 @@ doesn't exist." read-channel-metadata)) (lambda args (if (= ENOENT (system-error-errno args)) - (channel-metadata "/" '()) + (channel-metadata "/" '() #f) (apply throw args))))) (define (channel-instance-metadata instance) @@ -560,3 +572,98 @@ PROFILE is not a profile created by 'guix pull', return the empty list." ;; Show most recently installed packages last. (reverse (manifest-entries (profile-manifest profile))))) + + +;;; +;;; News. +;;; + +;; Channel news. +(define-record-type + (channel-news entries) + channel-news? + (entries channel-news-entries)) ;list of + +;; News entry, associated with a specific commit of the channel. +(define-record-type + (channel-news-entry commit title body) + channel-news-entry? + (commit channel-news-entry-commit) ;hex string + (title channel-news-entry-title) ;list of language tag/string pairs + (body channel-news-entry-body)) ;list of language tag/string pairs + +(define (sexp->channel-news-entry entry) + "Return the record corresponding to ENTRY, an sexp." + (define (pair language message) + (cons (symbol->string language) message)) + + (match entry + (('entry ('commit commit) + ('title ((? symbol? title-tags) (? string? titles)) ...) + ('body ((? symbol? body-tags) (? string? bodies)) ...) + _ ...) + (channel-news-entry commit + (map pair title-tags titles) + (map pair body-tags bodies))) + (_ + (raise (condition + (&message (message "invalid channel news entry")) + (&error-location + (location (source-properties->location + (source-properties entry))))))))) + +(define (read-channel-news port) + "Read a channel news feed from PORT and return it as a +record." + (match (false-if-exception (read port)) + (('channel-news ('version 0) entries ...) + (channel-news (map sexp->channel-news-entry entries))) + (('channel-news ('version version) _ ...) + ;; This is an unsupported version from the future. There's nothing wrong + ;; with that (the user may simply need to upgrade the 'guix' channel to + ;; be able to read it), so silently ignore it. + (channel-news '())) + (#f + (raise (condition + (&message (message "syntactically invalid channel news file"))))) + (sexp + (raise (condition + (&message (message "invalid channel news file")) + (&error-location + (location (source-properties->location + (source-properties sexp))))))))) + +(define* (channel-news-for-commit channel new #:optional old) + "Return a list of for CHANNEL between commits OLD and +NEW. When OLD is omitted or is #f, return all the news entries of CHANNEL." + (catch 'git-error + (lambda () + (let* ((checkout (update-cached-checkout (channel-url channel) + #:ref `(commit . ,new))) + (metadata (read-channel-metadata-from-source checkout)) + (news-file (channel-metadata-news-file metadata)) + (news-file (and news-file + (string-append checkout "/" news-file)))) + (if (and news-file (file-exists? news-file)) + (let ((entries (channel-news-entries (call-with-input-file news-file + read-channel-news)))) + (if old + (with-repository checkout repository + (let* ((new (commit-lookup repository (string->oid new))) + (old (commit-lookup repository (string->oid old))) + (commits (list->set + (map (compose oid->string commit-id) + (commit-difference new old))))) + (filter (lambda (entry) + (set-contains? commits + (channel-news-entry-commit entry))) + entries))) + entries)) + '()))) + (lambda (key error . rest) + ;; If commit NEW or commit OLD cannot be found, then something must be + ;; wrong (for example, the history of CHANNEL was rewritten and these + ;; commits no longer exist upstream), so quietly return the empty list. + (if (= GIT_ENOTFOUND (git-error-code error)) + '() + (apply throw key error rest))))) diff --git a/guix/tests/git.scm b/guix/tests/git.scm index 52abe77c83..9d5b1ae321 100644 --- a/guix/tests/git.scm +++ b/guix/tests/git.scm @@ -18,6 +18,7 @@ (define-module (guix tests git) #:use-module (git) + #:use-module ((guix git) #:select (with-repository)) #:use-module (guix utils) #:use-module (guix build utils) #:use-module (ice-9 match) @@ -55,7 +56,11 @@ Return DIRECTORY on success." (mkdir-p (dirname file)) (call-with-output-file file (lambda (port) - (display contents port))) + (display (if (string? contents) + contents + (with-repository directory repository + (contents repository))) + port))) (git "add" file) (loop rest))) ((('commit text) rest ...) diff --git a/tests/channels.scm b/tests/channels.scm index e83b5437d3..58101bcb72 100644 --- a/tests/channels.scm +++ b/tests/channels.scm @@ -28,6 +28,10 @@ #:use-module (guix gexp) #:use-module ((guix utils) #:select (error-location? error-location location-line)) + #:use-module ((guix build utils) #:select (which)) + #:use-module (git) + #:use-module (guix git) + #:use-module (guix tests git) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) @@ -246,4 +250,99 @@ (depends? drv3 (list drv2 drv0) (list)))))))) +(unless (which (git-command)) (test-skip 1)) +(test-equal "channel-news, no news" + '() + (with-temporary-git-repository directory + '((add "a.txt" "A") + (commit "the commit")) + (with-repository directory repository + (let ((channel (channel (url (string-append "file://" directory)) + (name 'foo))) + (latest (reference-name->oid repository "HEAD"))) + (channel-news-for-commit channel (oid->string latest)))))) + +(unless (which (git-command)) (test-skip 1)) +(test-assert "channel-news, one entry" + (with-temporary-git-repository directory + `((add ".guix-channel" + ,(object->string + '(channel (version 0) + (news-file "news.scm")))) + (commit "first commit") + (add "src/a.txt" "A") + (commit "second commit") + (add "news.scm" + ,(lambda (repository) + (let ((previous + (reference-name->oid repository "HEAD"))) + (object->string + `(channel-news + (version 0) + (entry (commit ,(oid->string previous)) + (title (en "New file!") + (eo "Nova dosiero!")) + (body (en "Yeah, a.txt.")))))))) + (commit "third commit") + (add "src/b.txt" "B") + (commit "fourth commit") + (add "news.scm" + ,(lambda (repository) + (let ((second + (commit-id + (find-commit repository "second commit"))) + (previous + (reference-name->oid repository "HEAD"))) + (object->string + `(channel-news + (version 0) + (entry (commit ,(oid->string previous)) + (title (en "Another file!")) + (body (en "Yeah, b.txt."))) + (entry (commit ,(oid->string second)) + (title (en "Old news.") + (eo "Malnovaĵoj.")) + (body (en "For a.txt")))))))) + (commit "fifth commit")) + (with-repository directory repository + (define (find-commit* message) + (oid->string (commit-id (find-commit repository message)))) + + (let ((channel (channel (url (string-append "file://" directory)) + (name 'foo))) + (commit1 (find-commit* "first commit")) + (commit2 (find-commit* "second commit")) + (commit3 (find-commit* "third commit")) + (commit4 (find-commit* "fourth commit")) + (commit5 (find-commit* "fifth commit"))) + ;; First try fetching all the news up to a given commit. + (and (null? (channel-news-for-commit channel commit2)) + (lset= string=? + (map channel-news-entry-commit + (channel-news-for-commit channel commit5)) + (list commit2 commit4)) + (lset= equal? + (map channel-news-entry-title + (channel-news-for-commit channel commit5)) + '((("en" . "Another file!")) + (("en" . "Old news.") ("eo" . "Malnovaĵoj.")))) + (lset= string=? + (map channel-news-entry-commit + (channel-news-for-commit channel commit3)) + (list commit2)) + + ;; Now fetch news entries that apply to a commit range. + (lset= string=? + (map channel-news-entry-commit + (channel-news-for-commit channel commit3 commit1)) + (list commit2)) + (lset= string=? + (map channel-news-entry-commit + (channel-news-for-commit channel commit5 commit3)) + (list commit4)) + (lset= string=? + (map channel-news-entry-commit + (channel-news-for-commit channel commit5 commit1)) + (list commit4 commit2))))))) + (test-end "channels") -- cgit v1.2.3 From 9719e8d37aaa63e1c8f9d4ab1e28d49e2e56d85b Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 21 Sep 2019 21:29:30 +0200 Subject: channels: Allow news entries to refer to a tag. Suggested by Ricardo Wurmus . * guix/channels.scm ()[tag]: New field. (sexp->channel-news-entry): Accept either 'commit' or 'tag' in 'entry' forms. (resolve-channel-news-entry-tag): New procedure. (channel-news-for-commit): Move 'with-repository' form one level higher. Call 'resolve-channel-news-entry-tag' on all the news entries. * guix/tests/git.scm (populate-git-repository): Add clause for 'tag'. * tests/channels.scm ("channel-news, one entry"): Create a tag and add an entry with a tag. Check that the tag is resolved and also visible in the record. * doc/guix.texi (Channels): Mention tags in news entries. --- doc/guix.texi | 8 ++++---- guix/channels.scm | 42 ++++++++++++++++++++++++++++++++---------- guix/tests/git.scm | 3 +++ tests/channels.scm | 9 +++++++-- 4 files changed, 46 insertions(+), 16 deletions(-) (limited to 'guix/tests/git.scm') diff --git a/doc/guix.texi b/doc/guix.texi index cd108faa8f..33bf08e9dd 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4018,7 +4018,7 @@ something like this: @lisp (channel-news (version 0) - (entry (commit "d894ab8e9bfabcefa6c49d9ba2e834dd5a73a300") + (entry (tag "the-bug-fix") (title (en "Fixed terrible bug") (fr "Oh la la")) (body (en "@@emph@{Good news@}! It's fixed!") @@ -4030,9 +4030,9 @@ something like this: @end lisp The file consists of a list of @dfn{news entries}. Each entry is -associated with a commit: it describes changes made in this commit, -possibly in preceding commits as well. Users see entries only the first -time they obtain the commit the entry refers to. +associated with a commit or tag: it describes changes made in this +commit, possibly in preceding commits as well. Users see entries only +the first time they obtain the commit the entry refers to. The @code{title} field should be a one-line summary while @code{body} can be arbitrarily long, and both can contain Texinfo markup diff --git a/guix/channels.scm b/guix/channels.scm index 0dadba616f..4e6e7090ac 100644 --- a/guix/channels.scm +++ b/guix/channels.scm @@ -40,6 +40,7 @@ #:use-module (srfi srfi-2) #:use-module (srfi srfi-9) #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:autoload (guix self) (whole-package make-config.scm) @@ -73,6 +74,7 @@ channel-news-entry? channel-news-entry-commit + channel-news-entry-tag channel-news-entry-title channel-news-entry-body @@ -586,9 +588,10 @@ PROFILE is not a profile created by 'guix pull', return the empty list." ;; News entry, associated with a specific commit of the channel. (define-record-type - (channel-news-entry commit title body) + (channel-news-entry commit tag title body) channel-news-entry? - (commit channel-news-entry-commit) ;hex string + (commit channel-news-entry-commit) ;hex string | #f + (tag channel-news-entry-tag) ;#f | string (title channel-news-entry-title) ;list of language tag/string pairs (body channel-news-entry-body)) ;list of language tag/string pairs @@ -598,11 +601,12 @@ PROFILE is not a profile created by 'guix pull', return the empty list." (cons (symbol->string language) message)) (match entry - (('entry ('commit commit) + (('entry ((and (or 'commit 'tag) type) commit-or-tag) ('title ((? symbol? title-tags) (? string? titles)) ...) ('body ((? symbol? body-tags) (? string? bodies)) ...) _ ...) - (channel-news-entry commit + (channel-news-entry (and (eq? type 'commit) commit-or-tag) + (and (eq? type 'tag) commit-or-tag) (map pair title-tags titles) (map pair body-tags bodies))) (_ @@ -633,6 +637,20 @@ record." (location (source-properties->location (source-properties sexp))))))))) +(define (resolve-channel-news-entry-tag repository entry) + "If ENTRY has its 'commit' field set, return ENTRY. Otherwise, lookup +ENTRY's 'tag' in REPOSITORY and return ENTRY with its 'commit' field set to +the field its 'tag' refers to. A 'git-error' exception is raised if the tag +cannot be found." + (if (channel-news-entry-commit entry) + entry + (let* ((tag (channel-news-entry-tag entry)) + (reference (string-append "refs/tags/" tag)) + (oid (reference-name->oid repository reference))) + (channel-news-entry (oid->string oid) tag + (channel-news-entry-title entry) + (channel-news-entry-body entry))))) + (define* (channel-news-for-commit channel new #:optional old) "Return a list of for CHANNEL between commits OLD and NEW. When OLD is omitted or is #f, return all the news entries of CHANNEL." @@ -645,10 +663,14 @@ NEW. When OLD is omitted or is #f, return all the news entries of CHANNEL." (news-file (and news-file (string-append checkout "/" news-file)))) (if (and news-file (file-exists? news-file)) - (let ((entries (channel-news-entries (call-with-input-file news-file - read-channel-news)))) - (if old - (with-repository checkout repository + (with-repository checkout repository + (let* ((news (call-with-input-file news-file + read-channel-news)) + (entries (map (lambda (entry) + (resolve-channel-news-entry-tag repository + entry)) + (channel-news-entries news)))) + (if old (let* ((new (commit-lookup repository (string->oid new))) (old (commit-lookup repository (string->oid old))) (commits (list->set @@ -657,8 +679,8 @@ NEW. When OLD is omitted or is #f, return all the news entries of CHANNEL." (filter (lambda (entry) (set-contains? commits (channel-news-entry-commit entry))) - entries))) - entries)) + entries)) + entries))) '()))) (lambda (key error . rest) ;; If commit NEW or commit OLD cannot be found, then something must be diff --git a/guix/tests/git.scm b/guix/tests/git.scm index 9d5b1ae321..21573ac14e 100644 --- a/guix/tests/git.scm +++ b/guix/tests/git.scm @@ -66,6 +66,9 @@ Return DIRECTORY on success." ((('commit text) rest ...) (git "commit" "-m" text) (loop rest)) + ((('tag name) rest ...) + (git "tag" name) + (loop rest)) ((('branch name) rest ...) (git "branch" name) (loop rest)) diff --git a/tests/channels.scm b/tests/channels.scm index 58101bcb72..f5a7955483 100644 --- a/tests/channels.scm +++ b/tests/channels.scm @@ -272,6 +272,7 @@ (commit "first commit") (add "src/a.txt" "A") (commit "second commit") + (tag "tag-for-first-news-entry") (add "news.scm" ,(lambda (repository) (let ((previous @@ -299,7 +300,7 @@ (entry (commit ,(oid->string previous)) (title (en "Another file!")) (body (en "Yeah, b.txt."))) - (entry (commit ,(oid->string second)) + (entry (tag "tag-for-first-news-entry") (title (en "Old news.") (eo "Malnovaĵoj.")) (body (en "For a.txt")))))))) @@ -343,6 +344,10 @@ (lset= string=? (map channel-news-entry-commit (channel-news-for-commit channel commit5 commit1)) - (list commit4 commit2))))))) + (list commit4 commit2)) + (lset= equal? + (map channel-news-entry-tag + (channel-news-for-commit channel commit5 commit1)) + '(#f "tag-for-first-news-entry"))))))) (test-end "channels") -- cgit v1.2.3