unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
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 --]

  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).