Subject: [bug#35456] [PATCH 1/1] guix package: Add 'install', 'remove', and 'upgrade' aliases.

From: Ludovic Courtès <[email-masked]>
Date: Sat, 27 Apr 2019 18:49:07 +0200

* guix/scripts/install.scm, guix/scripts/remove.scm,
guix/scripts/upgrade.scm, tests/guix-package-aliases.sh: New files.
* Makefile.am (MODULES, SH_TESTS): Add them.
* po/guix/POTFILES.in: Add them.
* guix/scripts/package.scm (guix-package): Split with...
(guix-package*): ... this.  New procedure.
* doc/guix.texi (Invoking guix package): Document them.
(Binary Installation, Application Setup, Package Management)
(Packages with Multiple Outputs, Package Modules)
(X.509 Certificates, Installing Debugging Files): Use 'guix install' in
simple examples.
---
 Makefile.am                   |  4 ++
 doc/guix.texi                 | 39 ++++++++++-----
 guix/scripts/install.scm      | 81 +++++++++++++++++++++++++++++++
 guix/scripts/package.scm      | 11 ++++-
 guix/scripts/remove.scm       | 78 ++++++++++++++++++++++++++++++
 guix/scripts/upgrade.scm      | 90 +++++++++++++++++++++++++++++++++++
 po/guix/POTFILES.in           |  3 ++
 tests/guix-package-aliases.sh | 58 ++++++++++++++++++++++
 8 files changed, 352 insertions(+), 12 deletions(-)
 create mode 100644 guix/scripts/install.scm
 create mode 100644 guix/scripts/remove.scm
 create mode 100644 guix/scripts/upgrade.scm
 create mode 100644 tests/guix-package-aliases.sh

diff --git a/Makefile.am b/Makefile.am
index f25900de0f..a1b97a2ca2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,6 +223,9 @@ MODULES =					\
   guix/scripts/archive.scm			\
   guix/scripts/import.scm			\
   guix/scripts/package.scm			\
+  guix/scripts/install.scm			\
+  guix/scripts/remove.scm			\
+  guix/scripts/upgrade.scm			\
   guix/scripts/gc.scm				\
   guix/scripts/hash.scm				\
   guix/scripts/pack.scm				\
@@ -424,6 +427,7 @@ SH_TESTS =					\
   tests/guix-pack-localstatedir.sh		\
   tests/guix-pack-relocatable.sh		\
   tests/guix-package.sh				\
+  tests/guix-package-aliases.sh			\
   tests/guix-package-net.sh			\
   tests/guix-system.sh				\
   tests/guix-archive.sh				\
diff --git a/doc/guix.texi b/doc/guix.texi
index 238fe9741f..6e33dde5a0 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -680,7 +680,7 @@ You can confirm that Guix is working by installing a sample package into
 the root profile:
 
 @example
-# guix package -i hello
+# guix install hello
 @end example
 
 The @code{guix} package must remain available in @code{root}'s profile,
@@ -1574,7 +1574,7 @@ available with Guix and then define the @code{GUIX_LOCPATH} environment
 variable:
 
 @example
-$ guix package -i glibc-locales
+$ guix install glibc-locales
 $ export GUIX_LOCPATH=$HOME/.guix-profile/lib/locale
 @end example
 
@@ -1674,7 +1674,7 @@ Multiple Outputs}).  For instance, the following command installs fonts
 for Chinese languages:
 
 @example
-guix package -i font-adobe-source-han-sans:cn
+guix install font-adobe-source-han-sans:cn
 @end example
 
 @cindex @code{xterm}
@@ -2489,7 +2489,7 @@ emacs-guix, The Emacs-Guix Reference Manual}), after installing
 with it):
 
 @example
-guix package -i emacs-guix
+guix install emacs-guix
 @end example
 
 @menu
@@ -2607,6 +2607,7 @@ is:
 @example
 guix package @var{options}
 @end example
+
 @cindex transactions
 Primarily, @var{options} specifies the operations to be performed during
 the transaction.  Upon completion, a new profile is created, but
@@ -2620,6 +2621,22 @@ For example, to remove @code{lua} and install @code{guile} and
 guix package -r lua -i guile guile-cairo
 @end example
 
+@cindex aliases, for @command{guix package}
+For your convenience, we also provide the following aliases:
+
+@itemize
+@item
+@command{guix install} is an alias for @command{guix package -i},
+@item
+@command{guix remove} is an alias for @command{guix package -r},
+@item
+and @command{guix upgrade} is an alias for @command{guix package -u}.
+@end itemize
+
+These aliases are less expressive than @command{guix package} and provide
+fewer options, so in some cases you'll probably want to use @command{guix
+package} directly.
+
 @command{guix package} also supports a @dfn{declarative approach}
 whereby the user specifies the exact set of packages to be available and
 passes it @i{via} the @option{--manifest} option
@@ -3309,7 +3326,7 @@ like to discuss this project, join us on @email{guix-devel@@gnu.org}.
 
 Often, packages defined in Guix have a single @dfn{output}---i.e., the
 source package leads to exactly one directory in the store.  When running
-@command{guix package -i glibc}, one installs the default output of the
+@command{guix install glibc}, one installs the default output of the
 GNU libc package; the default output is called @code{out}, but its name
 can be omitted as shown in this command.  In this particular case, the
 default output of @code{glibc} contains all the C header files, shared
@@ -3325,14 +3342,14 @@ separate output, called @code{doc}.  To install the main GLib output,
 which contains everything but the documentation, one would run:
 
 @example
-guix package -i glib
+guix install glib
 @end example
 
 @cindex documentation
 The command to install its documentation is:
 
 @example
-guix package -i glib:doc
+guix install glib:doc
 @end example
 
 Some packages install programs with different ``dependency footprints''.
@@ -4983,7 +5000,7 @@ module exports a variable named @code{emacs}, which is bound to a
 
 The @code{(gnu packages @dots{})} module name space is
 automatically scanned for packages by the command-line tools.  For
-instance, when running @code{guix package -i emacs}, all the @code{(gnu
+instance, when running @code{guix install emacs}, all the @code{(gnu
 packages @dots{})} modules are scanned until one that exports a package
 object whose name is @code{emacs} is found.  This package search
 facility is implemented in the @code{(gnu packages)} module.
@@ -23631,7 +23648,7 @@ pointed to by the @code{GIT_SSL_CAINFO} environment variable.  Thus, you
 would typically run something like:
 
 @example
-$ guix package -i nss-certs
+$ guix install nss-certs
 $ export SSL_CERT_DIR="$HOME/.guix-profile/etc/ssl/certs"
 $ export SSL_CERT_FILE="$HOME/.guix-profile/etc/ssl/certs/ca-certificates.crt"
 $ export GIT_SSL_CAINFO="$SSL_CERT_FILE"
@@ -23642,7 +23659,7 @@ variable to point to a certificate bundle, so you would have to run
 something like this:
 
 @example
-$ guix package -i nss-certs
+$ guix install nss-certs
 $ export CURL_CA_BUNDLE="$HOME/.guix-profile/etc/ssl/certs/ca-certificates.crt"
 @end example
 
@@ -25424,7 +25441,7 @@ installs the debugging information for the GNU C Library and for GNU
 Guile:
 
 @example
-guix package -i glibc:debug guile:debug
+guix install glibc:debug guile:debug
 @end example
 
 GDB must then be told to look for debug files in the user's profile, by
diff --git a/guix/scripts/install.scm b/guix/scripts/install.scm
new file mode 100644
index 0000000000..611ed1f712
--- /dev/null
+++ b/guix/scripts/install.scm
@@ -0,0 +1,81 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Ludovic Courtès <[email-masked]>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts install)
+  #:use-module (guix ui)
+  #:use-module (guix scripts package)
+  #:use-module (guix scripts build)
+  #:use-module (guix scripts)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-37)
+  #:export (guix-install))
+
+(define (show-help)
+  (display (G_ "Usage: guix install [OPTION] PACKAGES...
+Install the given PACKAGES.
+This is an alias for 'guix package -i'.\n"))
+  (display (G_ "
+  -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
+  (display (G_ "
+      --bootstrap        use the bootstrap Guile to build the profile"))
+  (display (G_ "
+  -v, --verbosity=LEVEL  use the given verbosity LEVEL"))
+  (newline)
+  (show-build-options-help)
+  (newline)
+  (show-transformation-options-help)
+  (newline)
+  (display (G_ "
+  -h, --help             display this help and exit"))
+  (display (G_ "
+  -V, --version          display version information and exit"))
+  (newline)
+  (show-bug-report-information))
+
+(define %options
+  ;; Specification of the command-line options.
+  (cons* (option '(#\h "help") #f #f
+                 (lambda args
+                   (show-help)
+                   (exit 0)))
+         (option '(#\V "version") #f #f
+                 (lambda args
+                   (show-version-and-exit "guix install")))
+
+         ;; Preserve some of the 'guix package' options.
+         (append (filter (lambda (option)
+                           (any (cut member <> (option-names option))
+                                '("profile" "dry-run" "verbosity" "bootstrap")))
+                         %package-options)
+
+                 %transformation-options
+                 %standard-build-options)))
+
+(define (guix-install . args)
+  (define (handle-argument arg result arg-handler)
+    ;; Treat all non-option arguments as package specs.
+    (values (alist-cons 'install arg result)
+            arg-handler))
+
+  (define opts
+    (parse-command-line args %options
+                        (list %package-default-options #f)
+                        #:argument-handler handle-argument))
+
+  (guix-package* opts))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index 564236988e..aa27984ea2 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -58,7 +58,11 @@
             delete-generations
             delete-matching-generations
             display-search-paths
-            guix-package))
+            guix-package
+
+            (%options . %package-options)
+            (%default-options . %package-default-options)
+            guix-package*))
 
 (define %store
   (make-parameter #f))
@@ -899,6 +903,11 @@ processed, #f otherwise."
     (parse-command-line args %options (list %default-options #f)
                         #:argument-handler handle-argument))
 
+  (guix-package* opts))
+
+(define (guix-package* opts)
+  "Run the 'guix package' command on OPTS, an alist resulting for command-line
+option processing with 'parse-command-line'."
   (with-error-handling
     (or (process-query opts)
         (parameterize ((%store  (open-connection))
diff --git a/guix/scripts/remove.scm b/guix/scripts/remove.scm
new file mode 100644
index 0000000000..9204740d65
--- /dev/null
+++ b/guix/scripts/remove.scm
@@ -0,0 +1,78 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Ludovic Courtès <[email-masked]>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts remove)
+  #:use-module (guix ui)
+  #:use-module (guix scripts package)
+  #:use-module (guix scripts build)
+  #:use-module (guix scripts)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-37)
+  #:export (guix-remove))
+
+(define (show-help)
+  (display (G_ "Usage: guix remove [OPTION] PACKAGES...
+Remove the given PACKAGES.
+This is an alias for 'guix package -r'.\n"))
+  (display (G_ "
+  -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
+  (display (G_ "
+      --bootstrap        use the bootstrap Guile to build the profile"))
+  (display (G_ "
+  -v, --verbosity=LEVEL  use the given verbosity LEVEL"))
+  (newline)
+  (show-build-options-help)
+  (newline)
+  (display (G_ "
+  -h, --help             display this help and exit"))
+  (display (G_ "
+  -V, --version          display version information and exit"))
+  (newline)
+  (show-bug-report-information))
+
+(define %options
+  ;; Specification of the command-line options.
+  (cons* (option '(#\h "help") #f #f
+                 (lambda args
+                   (show-help)
+                   (exit 0)))
+         (option '(#\V "version") #f #f
+                 (lambda args
+                   (show-version-and-exit "guix remove")))
+
+         ;; Preserve some of the 'guix package' options.
+         (append (filter (lambda (option)
+                           (any (cut member <> (option-names option))
+                                '("profile" "dry-run" "verbosity" "bootstrap")))
+                         %package-options)
+
+                 %standard-build-options)))
+
+(define (guix-remove . args)
+  (define (handle-argument arg result arg-handler)
+    ;; Treat all non-option arguments as package specs.
+    (values (alist-cons 'remove arg result)
+            arg-handler))
+
+  (define opts
+    (parse-command-line args %options
+                        (list %package-default-options #f)
+                        #:argument-handler handle-argument))
+
+  (guix-package* opts))
diff --git a/guix/scripts/upgrade.scm b/guix/scripts/upgrade.scm
new file mode 100644
index 0000000000..bf3b8a0710
--- /dev/null
+++ b/guix/scripts/upgrade.scm
@@ -0,0 +1,90 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Ludovic Courtès <[email-masked]>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts upgrade)
+  #:use-module (guix ui)
+  #:use-module (guix scripts package)
+  #:use-module (guix scripts build)
+  #:use-module (guix scripts)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:use-module (srfi srfi-37)
+  #:use-module (ice-9 match)
+  #:export (guix-upgrade))
+
+(define (show-help)
+  (display (G_ "Usage: guix upgrade [OPTION] [REGEXP]
+Upgrade packages that match REGEXP.
+This is an alias for 'guix package -u'.\n"))
+  (display (G_ "
+  -p, --profile=PROFILE  use PROFILE instead of the user's default profile"))
+  (display (G_ "
+      --bootstrap        use the bootstrap Guile to build the profile"))
+  (display (G_ "
+  -v, --verbosity=LEVEL  use the given verbosity LEVEL"))
+  (newline)
+  (show-build-options-help)
+  (newline)
+  (show-transformation-options-help)
+  (newline)
+  (display (G_ "
+  -h, --help             display this help and exit"))
+  (display (G_ "
+  -V, --version          display version information and exit"))
+  (newline)
+  (show-bug-report-information))
+
+(define %options
+  ;; Specification of the command-line options.
+  (cons* (option '(#\h "help") #f #f
+                 (lambda args
+                   (show-help)
+                   (exit 0)))
+         (option '(#\V "version") #f #f
+                 (lambda args
+                   (show-version-and-exit "guix upgrade")))
+
+         ;; Preserve some of the 'guix package' options.
+         (append (filter (lambda (option)
+                           (any (cut member <> (option-names option))
+                                '("profile" "dry-run" "verbosity" "bootstrap")))
+                         %package-options)
+
+                 %transformation-options
+                 %standard-build-options)))
+
+(define (guix-upgrade . args)
+  (define (handle-argument arg result arg-handler)
+    ;; Accept at most one non-option argument, and treat it as an upgrade
+    ;; regexp.
+    (match (assq-ref result 'upgrade)
+      (#f
+       (values (alist-cons 'upgrade arg
+                           (alist-delete 'upgrade result))
+               arg-handler))
+      (_
+       (leave (G_ "~A: extraneous argument~%") arg))))
+
+  (define opts
+    (parse-command-line args %options
+                        (list `((upgrade . #f)
+                                ,@%package-default-options)
+                              #f)
+                        #:argument-handler handle-argument))
+
+  (guix-package* opts))
diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in
index a2c89db981..91de60efc7 100644
--- a/po/guix/POTFILES.in
+++ b/po/guix/POTFILES.in
@@ -41,6 +41,9 @@ guix/scripts/build.scm
 guix/discovery.scm
 guix/scripts/download.scm
 guix/scripts/package.scm
+guix/scripts/install.scm
+guix/scripts/remove.scm
+guix/scripts/upgrade.scm
 guix/scripts/gc.scm
 guix/scripts/hash.scm
 guix/scripts/import.scm
diff --git a/tests/guix-package-aliases.sh b/tests/guix-package-aliases.sh
new file mode 100644
index 0000000000..64ed2fbb67
--- /dev/null
+++ b/tests/guix-package-aliases.sh
@@ -0,0 +1,58 @@
+# GNU Guix --- Functional package management for GNU
+# Copyright © 2019 Ludovic Courtès <[email-masked]>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+#
+# Test the `guix package' aliases.
+#
+
+guix install --version
+
+readlink_base ()
+{
+    basename `readlink "$1"`
+}
+
+profile="t-profile-$$"
+rm -f "$profile"
+
+trap 'rm -f "$profile" "$profile-"[0-9]*' EXIT
+
+guix install --bootstrap guile-bootstrap -p "$profile"
+test -x "$profile/bin/guile"
+
+# Make sure '-r' isn't passed as-is to 'guix package'.
+if guix install -r guile-bootstrap -p "$profile" --bootstrap
+then false; else true; fi
+test -x "$profile/bin/guile"
+
+guix upgrade --version
+guix upgrade -n
+guix upgrade gui.e -n
+if guix upgrade foo bar -n;
+then false; else true; fi
+
+guix remove --version
+guix remove --bootstrap guile-bootstrap -p "$profile"
+! test -x "$profile/bin/guile"
+test `guix package -p "$profile" -I | wc -l` -eq 0
+
+if guix remove -p "$profile" this-is-not-installed --bootstrap
+then false; else true; fi
+
+if guix remove -i guile-bootstrap -p "$profile" --bootstrap
+then false; else true; fi
-- 
2.21.0