From: Nikita Karetnikov <nikita@karetnikov.org>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: guix-devel@gnu.org
Subject: Re: New ‘--list-generations’ and ‘--delete-generations’ options
Date: Fri, 13 Sep 2013 18:44:34 +0400 [thread overview]
Message-ID: <87zjrgok6l.fsf@karetnikov.org> (raw)
In-Reply-To: <87zjrins47.fsf@gnu.org> ("Ludovic Courtès"'s message of "Thu, 12 Sep 2013 14:26:16 +0200")
[-- Attachment #1.1: Type: text/plain, Size: 765 bytes --]
> I’d prefer clearer case analysis as shown above.
OK, what do you think about this diff? If everything is fine, I’ll make
it output generations in the recutils format.
(Is it necessary to mention that ‘maybe-comma-separated-integers’ accepts
something like ‘1,2,3,’ or ‘1,,,2’. Or should I change the function?)
I don’t know if the code works with non-default profiles because my
store is broken. When I try to install or build a new package (with or
without substitutes), I get the following message:
guix package: error: build failed: getting attributes of path `/nix/store/fcwh19ljibqjfx0c3cwnwcc7p31aq227-glibc-2.17-locales': No such file or directory
I’ve already tried to run ‘guix gc’, but it didn’t help.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: list-generations.diff --]
[-- Type: text/x-diff, Size: 7076 bytes --]
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 1393ca3..6e8171c 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -34,6 +34,7 @@
#:use-module (ice-9 vlist)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-37)
@@ -246,6 +247,127 @@ all of PACKAGES, a list of name/version/output/path/deps tuples."
(switch-link)))
(else (switch-link))))) ; anything else
+(define (string->generations str)
+ "Return a list of generations matching a pattern in STR. This function
+accepts the following patterns: \"1\", \"1,2,3\", \"1..9\", \"1..\", \"..9\"."
+ (define (maybe-integer)
+ (let ((x (string->number str)))
+ (and (integer? x)
+ x)))
+
+ (define (maybe-comma-separated-integers)
+ (let ((lst (delete-duplicates
+ (map string->number
+ (delete "" (string-split str #\,))))))
+ (and (every integer? lst)
+ lst)))
+
+ (cond ((maybe-integer)
+ =>
+ list)
+ ((maybe-comma-separated-integers)
+ =>
+ identity)
+ ((string-match "^([0-9]+)\\.\\.([0-9]+)$" str)
+ =>
+ (lambda (match)
+ (let ((s (string->number (match:substring match 1)))
+ (e (string->number (match:substring match 2))))
+ (and (every integer? (list s e))
+ (<= s e)
+ (iota (1+ (- e s)) s)))))
+ ((string-match "^([0-9]+)\\.\\.$" str)
+ =>
+ (lambda (match)
+ (let ((s (string->number (match:substring match 1))))
+ (and (integer? s)
+ `(>= ,s)))))
+ ((string-match "^\\.\\.([0-9]+)$" str)
+ =>
+ (lambda (match)
+ (let ((e (string->number (match:substring match 1))))
+ (and (integer? e)
+ `(<= ,e)))))
+ (else #f)))
+
+(define (string->duration str)
+ "Return a duration matching a pattern in STR. This function accepts the
+following patterns: \"1d\", \"1w\", \"1m\"."
+ (define (hours->duration hours match)
+ (make-time time-duration 0
+ (* 3600 hours (string->number (match:substring match 1)))))
+
+ (cond ((string-match "^([0-9]+)d$" str)
+ =>
+ (lambda (match)
+ (hours->duration 24 match)))
+ ((string-match "^([0-9]+)w$" str)
+ =>
+ (lambda (match)
+ (hours->duration (* 24 7) match)))
+ ((string-match "^([0-9]+)m$" str)
+ =>
+ (lambda (match)
+ (hours->duration (* 24 30) match)))
+ (else #f)))
+
+(define* (available-generations str #:optional (profile %current-profile))
+ "Return a list of available generations matching pattern in STR. See
+'string->generations' and 'string->duration' for a list of valid patterns."
+ (define (valid-generations lst)
+ (define (valid-generation? n)
+ (any (cut = n <>) (generation-numbers profile)))
+
+ (fold-right (lambda (x acc)
+ (if (valid-generation? x)
+ (cons x acc)
+ acc))
+ '()
+ lst))
+
+ (define (filter-generations generations)
+ (match generations
+ (() '())
+ (('>= n)
+ (drop-while (cut > n <>)
+ (generation-numbers profile)))
+ (('<= n)
+ (valid-generations (iota n 1)))
+ ((lst ..1)
+ (valid-generations lst))
+ (_ #f)))
+
+ (define (filter-by-duration duration)
+ (define dates-generations
+ ;; Return an alist of dates and generations.
+ (map (lambda (x)
+ (cons (and=> (stat (format #f "~a-~a-link"
+ profile (number->string x)))
+ stat:ctime)
+ x))
+ (generation-numbers profile)))
+
+ (define dates
+ (fold-right (lambda (x acc)
+ (cons (first x) acc))
+ '()
+ dates-generations))
+
+ (match duration
+ (#f #f)
+ (res
+ (let ((s (time-second (subtract-duration (current-time) duration))))
+ (map (cut assoc-ref dates-generations <>)
+ (filter (cut <= s <>) dates))))))
+
+ (cond ((string->generations str)
+ =>
+ filter-generations)
+ ((string->duration str)
+ =>
+ filter-by-duration)
+ (else #f)))
+
(define (find-packages-by-description rx)
"Search in SYNOPSIS and DESCRIPTION using RX. Return a list of
matching packages."
@@ -441,6 +563,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
--roll-back roll back to the previous generation"))
(display (_ "
--search-paths display needed environment variable definitions"))
+ (display (_ "
+ -l --list-generations[=REGEXP]
+ list generations matching REGEXP"))
(newline)
(display (_ "
-p, --profile=PROFILE use PROFILE instead of the user's default profile"))
@@ -500,6 +625,10 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
(option '("roll-back") #f #f
(lambda (opt name arg result)
(alist-cons 'roll-back? #t result)))
+ (option '(#\l "list-generations") #f #t
+ (lambda (opt name arg result)
+ (cons `(query list-generations ,(or arg ""))
+ result)))
(option '("search-paths") #f #f
(lambda (opt name arg result)
(cons `(query search-paths) result)))
@@ -879,6 +1008,24 @@ more information.~%"))
;; actually processed, #f otherwise.
(let ((profile (assoc-ref opts 'profile)))
(match (assoc-ref opts 'query)
+ (('list-generations regexp)
+ (define* (list-generation number)
+ (begin
+ (format #t "Generation ~a:~%" (number->string number))
+ (for-each (match-lambda
+ ((name version output location _)
+ (format #t "~a\t~a\t~a\t~a~%"
+ name version output location)))
+ (manifest-packages
+ (profile-manifest
+ (format #f "~a-~a-link" profile number))))))
+
+ (let ((lst (if (string-null? regexp)
+ (generation-numbers profile)
+ (or (available-generations regexp profile)
+ (leave (_ "invalid syntax: ~a~%") regexp)))))
+ (for-each list-generation lst)))
+
(('list-installed regexp)
(let* ((regexp (and regexp (make-regexp regexp)))
(manifest (profile-manifest profile))
[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]
next prev parent reply other threads:[~2013-09-13 14:40 UTC|newest]
Thread overview: 132+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-29 12:34 Goals for 0.4 Ludovic Courtès
2013-08-29 13:16 ` Nikita Karetnikov
2013-08-29 13:36 ` Ludovic Courtès
2013-08-30 17:55 ` Nikita Karetnikov
2013-08-30 18:31 ` Ludovic Courtès
2013-08-31 16:40 ` Nikita Karetnikov
2013-08-31 18:05 ` Ludovic Courtès
2013-08-31 20:34 ` Jose E. Marchesi
2013-08-31 21:07 ` Ludovic Courtès
2013-09-01 23:16 ` New ‘--list-generations’ and ‘--delete-generations’ options (was: Goals for 0.4) Nikita Karetnikov
2013-09-02 9:08 ` New ‘--list-generations’ and ‘--delete-generations’ options Ludovic Courtès
2013-09-05 1:30 ` Nikita Karetnikov
2013-09-05 20:00 ` Ludovic Courtès
2013-09-05 21:14 ` Nikita Karetnikov
2013-09-07 19:34 ` Ludovic Courtès
2013-09-08 10:59 ` Nikita Karetnikov
2013-09-08 20:22 ` Ludovic Courtès
2013-09-09 9:17 ` Nikita Karetnikov
2013-09-09 16:55 ` Ludovic Courtès
2013-09-11 5:16 ` Nikita Karetnikov
2013-09-11 21:25 ` Ludovic Courtès
2013-09-12 9:17 ` Nikita Karetnikov
2013-09-12 12:26 ` Ludovic Courtès
2013-09-13 14:44 ` Nikita Karetnikov [this message]
2013-09-13 21:29 ` Ludovic Courtès
2013-09-16 11:12 ` Nikita Karetnikov
2013-09-16 12:16 ` Ludovic Courtès
2013-09-18 0:43 ` PRELIMINARY: [PATCH] guix package: Add '--list-generations' Nikita Karetnikov
2013-09-18 17:35 ` Nikita Karetnikov
2013-09-18 21:32 ` Ludovic Courtès
2013-09-19 0:49 ` Nikita Karetnikov
2013-09-19 9:39 ` Ludovic Courtès
2013-09-19 11:48 ` Nikita Karetnikov
2013-09-19 12:13 ` Ludovic Courtès
2013-09-21 20:39 ` Ludovic Courtès
2013-09-18 21:35 ` PRELIMINARY: " Ludovic Courtès
2013-09-22 19:19 ` [PATCH] guix package: Add '--delete-generations' Nikita Karetnikov
2013-09-22 20:15 ` Generation 0 (was: [PATCH] guix package: Add '--delete-generations'.) Nikita Karetnikov
2013-09-22 21:15 ` Generation 0 Ludovic Courtès
2013-09-23 10:14 ` Nikita Karetnikov
2013-09-23 15:42 ` Ludovic Courtès
2013-09-24 0:54 ` Nikita Karetnikov
2013-09-24 5:56 ` [PATCH] guix package: Show which generation is the current one. (was: Generation 0) Nikita Karetnikov
2013-09-24 12:45 ` [PATCH] guix package: Show which generation is the current one Ludovic Courtès
2013-09-24 13:55 ` Nikita Karetnikov
2013-09-24 14:16 ` Ludovic Courtès
2013-09-25 2:10 ` Nikita Karetnikov
2013-09-25 12:51 ` Ludovic Courtès
2013-09-24 12:43 ` Generation 0 Ludovic Courtès
2013-09-24 22:29 ` Nikita Karetnikov
2013-09-25 12:50 ` Ludovic Courtès
2013-09-25 18:07 ` Nikita Karetnikov
2013-09-25 19:24 ` Ludovic Courtès
2013-09-26 2:18 ` Nikita Karetnikov
2013-09-26 9:44 ` Ludovic Courtès
2013-09-22 20:55 ` [PATCH] guix package: Add '--delete-generations' Ludovic Courtès
2013-09-23 10:11 ` Nikita Karetnikov
2013-09-23 15:41 ` Ludovic Courtès
2013-09-24 7:21 ` Nikita Karetnikov
2013-09-24 12:50 ` Ludovic Courtès
2013-09-24 13:57 ` Nikita Karetnikov
2013-09-25 4:21 ` Nikita Karetnikov
2013-09-25 13:05 ` Ludovic Courtès
2013-09-26 2:47 ` Nikita Karetnikov
2013-09-26 9:49 ` Ludovic Courtès
2013-09-27 19:04 ` Ludovic Courtès
2013-09-03 19:21 ` MIPS64/N64 support (was: Goals for 0.4) Nikita Karetnikov
2013-09-03 20:45 ` MIPS64/N64 support Ludovic Courtès
2013-09-04 0:35 ` Nikita Karetnikov
2013-09-04 12:18 ` Ludovic Courtès
2013-09-06 8:35 ` Nikita Karetnikov
2013-09-06 9:46 ` Ludovic Courtès
2013-09-07 2:45 ` Nikita Karetnikov
2013-09-07 12:57 ` Ludovic Courtès
2013-09-08 14:21 ` Nikita Karetnikov
2013-09-08 19:54 ` Ludovic Courtès
2013-09-09 5:38 ` Nikita Karetnikov
2013-09-09 16:47 ` Ludovic Courtès
2013-09-27 2:16 ` Nikita Karetnikov
2013-09-27 19:00 ` Ludovic Courtès
2013-09-29 13:27 ` Nikita Karetnikov
2013-09-29 13:31 ` Ludovic Courtès
2013-09-29 23:18 ` Nikita Karetnikov
2013-09-30 11:32 ` Nikita Karetnikov
2013-09-30 16:26 ` Ludovic Courtès
2013-09-30 21:51 ` Nikita Karetnikov
2013-10-01 7:09 ` Lluís Batlle i Rossell
2013-10-01 7:48 ` Nikita Karetnikov
2013-10-01 8:03 ` Lluís Batlle i Rossell
2013-10-01 8:55 ` Nikita Karetnikov
2013-10-01 8:59 ` Nikita Karetnikov
2013-10-01 9:30 ` Lluís Batlle i Rossell
2013-10-01 10:06 ` Nikita Karetnikov
2013-10-01 10:04 ` Lluís Batlle i Rossell
2013-10-01 11:25 ` Ludovic Courtès
2013-10-01 11:56 ` Lluís Batlle i Rossell
2013-10-07 18:47 ` Mark H Weaver
2013-10-07 19:39 ` Ludovic Courtès
2013-10-08 23:03 ` Mark H Weaver
2013-10-09 6:53 ` Mark H Weaver
2013-10-09 10:42 ` Ludovic Courtès
2013-10-09 10:39 ` Ludovic Courtès
2013-10-10 4:08 ` Mark H Weaver
2013-09-30 16:09 ` Ludovic Courtès
2013-08-29 15:49 ` Goals for 0.4 Amirouche Boubekki
2013-08-29 20:04 ` Ludovic Courtès
2013-08-30 16:09 ` Cyprien Nicolas
2013-08-30 17:40 ` Amirouche Boubekki
2013-08-30 19:31 ` Overlays Ludovic Courtès
2013-08-30 20:42 ` Overlays Nikita Karetnikov
2013-08-30 21:21 ` Overlays Ludovic Courtès
2013-08-31 10:56 ` Overlays Amirouche Boubekki
2013-08-31 15:57 ` Overlays Ludovic Courtès
2013-08-29 20:42 ` Goals for 0.4 Andreas Enge
2013-08-29 21:32 ` Ludovic Courtès
2013-09-25 8:43 ` Andreas Enge
2013-09-25 13:13 ` Ludovic Courtès
2013-09-26 11:35 ` Andreas Enge
2013-09-28 13:25 ` Ludovic Courtès
2013-09-29 21:29 ` Alex Sassmannshausen
2013-09-02 17:33 ` Cyril Roelandt
2013-09-02 19:38 ` Ludovic Courtès
2013-09-02 19:40 ` Cyril Roelandt
2013-09-02 21:35 ` Ludovic Courtès
2013-09-06 9:19 ` ‘--no-substitutes’ is ignored on i686 (was: Goals for 0.4) Nikita Karetnikov
2013-09-06 9:59 ` ‘--no-substitutes’ is ignored on i686 Ludovic Courtès
2013-09-07 8:43 ` Nikita Karetnikov
2013-09-07 13:00 ` Ludovic Courtès
2013-09-08 11:53 ` Nikita Karetnikov
2013-09-08 11:51 ` Cyril Roelandt
2013-09-08 13:22 ` Nikita Karetnikov
2013-09-24 21:59 ` Goals for 0.4 Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87zjrgok6l.fsf@karetnikov.org \
--to=nikita@karetnikov.org \
--cc=guix-devel@gnu.org \
--cc=ludo@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).