From da551107129d22dfb2a4278a55b702a7340e7f51 Mon Sep 17 00:00:00 2001 From: Konrad Hinsen Date: Wed, 18 Sep 2019 09:52:18 +0200 Subject: [PATCH] scripts: pull: Add options for generation management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/pull.scm (%options) Add --roll-back, --switch-generation, --delete-generations (process-generation-change): New function (guix-pull): Execute generation management operations * doc/guix.texi: Document the generation management operations Signed-off-by: Ludovic Courtès --- doc/guix.texi | 47 +++++++++++++++++++++++++++++++++++++++++-- guix/scripts/pull.scm | 41 ++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index da62194a16..0ed59072c9 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -3673,11 +3673,20 @@ Generation 3 Jun 13 2018 23:31:07 (current) @xref{Invoking guix describe, @command{guix describe}}, for other ways to describe the current status of Guix. -This @code{~/.config/guix/current} profile works like any other profile -created by @command{guix package} (@pxref{Invoking guix package}). That +This @code{~/.config/guix/current} profile works exactly like the profiles +created by @command{guix package} (@pxref{Invoking guix package}). That is, you can list generations, roll back to the previous generation---i.e., the previous Guix---and so on: +@example +$ guix pull --roll-back +switched from generation 3 to 2 +$ guix pull --delete-generations=1 +deleting /var/guix/profiles/per-user/charlie/current-guix-1-link +@end example + +You can also use @command{guix package} (@pxref{Invoking guix package}) +to manage the profile by naming it explicitly: @example $ guix package -p ~/.config/guix/current --roll-back switched from generation 3 to 2 @@ -3724,6 +3733,40 @@ is provided, the subset of generations that match @var{pattern}. The syntax of @var{pattern} is the same as with @code{guix package --list-generations} (@pxref{Invoking guix package}). +@item --roll-back +@cindex rolling back +@cindex undoing transactions +@cindex transactions, undoing +Roll back to the previous @dfn{generation} of @file{~/.config/guix/current}---i.e., +undo the last transaction. + +@item --switch-generation=@var{pattern} +@itemx -S @var{pattern} +@cindex generations +Switch to a particular generation defined by @var{pattern}. + +@var{pattern} may be either a generation number or a number prefixed +with ``+'' or ``-''. The latter means: move forward/backward by a +specified number of generations. For example, if you want to return to +the latest generation after @code{--roll-back}, use +@code{--switch-generation=+1}. + +@item --delete-generations[=@var{pattern}] +@itemx -d [@var{pattern}] +When @var{pattern} is omitted, delete all generations except the current +one. + +This command accepts the same patterns as @option{--list-generations}. +When @var{pattern} is specified, delete the matching generations. When +@var{pattern} specifies a duration, generations @emph{older} than the +specified duration match. For instance, @code{--delete-generations=1m} +deletes generations that are more than one month old. + +If the current generation matches, it is @emph{not} deleted. + +Note that deleting generations prevents rolling back to them. +Consequently, this command must be used with care. + @xref{Invoking guix describe}, for a way to display information about the current generation only. diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm index 4b03cea2e3..c9835cef34 100644 --- a/guix/scripts/pull.scm +++ b/guix/scripts/pull.scm @@ -38,7 +38,8 @@ #:use-module (guix git) #:use-module (git) #:use-module (gnu packages) - #:use-module ((guix scripts package) #:select (build-and-use-profile)) + #:use-module ((guix scripts package) #:select (build-and-use-profile + delete-matching-generations)) #:use-module ((gnu packages base) #:select (canonical-package)) #:use-module (gnu packages guile) #:use-module ((gnu packages bootstrap) @@ -91,6 +92,14 @@ Download and deploy the latest version of Guix.\n")) (display (G_ " -l, --list-generations[=PATTERN] list generations matching PATTERN")) + (display (G_ " + --roll-back roll back to the previous generation")) + (display (G_ " + -d, --delete-generations[=PATTERN] + delete generations matching PATTERN")) + (display (G_ " + -S, --switch-generation=PATTERN + switch to a generation matching PATTERN")) (display (G_ " -p, --profile=PROFILE use PROFILE instead of ~/.config/guix/current")) (display (G_ " @@ -120,6 +129,18 @@ Download and deploy the latest version of Guix.\n")) (lambda (opt name arg result) (cons `(query list-generations ,arg) result))) + (option '("roll-back") #f #f + (lambda (opt name arg result) + (cons '(generation roll-back) + result))) + (option '(#\S "switch-generation") #t #f + (lambda (opt name arg result) + (cons `(generation switch ,arg) + result))) + (option '(#\d "delete-generations") #f #t + (lambda (opt name arg result) + (cons `(generation delete ,arg) + result))) (option '(#\N "news") #f #f (lambda (opt name arg result) (cons '(query display-news) result))) @@ -505,6 +526,22 @@ list of package changes."))))) (display-profile-news profile #:current-is-newer? #t)))) +(define (process-generation-change opts profile) + "Process a request to change the current generation (roll-back, switch, delete)." + (unless (assoc-ref opts 'dry-run?) + (match (assoc-ref opts 'generation) + (('roll-back) + (with-store store + (roll-back* store profile))) + (('switch pattern) + (let ((number (relative-generation-spec->number profile pattern))) + (if number + (switch-to-generation* profile number) + (leave (G_ "cannot switch to generation '~a'~%") pattern)))) + (('delete pattern) + (with-store store + (delete-matching-generations store profile pattern)))))) + (define (channel-list opts) "Return the list of channels to use. If OPTS specify a channel file, channels are read from there; otherwise, if ~/.config/guix/channels.scm @@ -572,6 +609,8 @@ Use '~/.config/guix/channels.scm' instead.")) (profile (or (assoc-ref opts 'profile) %current-profile))) (cond ((assoc-ref opts 'query) (process-query opts profile)) + ((assoc-ref opts 'generation) + (process-generation-change opts profile)) (else (with-store store (ensure-default-profile)