Subject: bug#22933: M-x guix-edit fails gracelessly when passed an nonexistent package name

From: [email-masked] (Ludovic Courtès)
Date: Mon, 07 Mar 2016 17:28:48 +0100

Currently M-x guix-edit fails badly (actually ‘guix-package-location’)
pwhen passed the name of a nonexistent package:

--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Error in evaluating guile expression: ERROR: In procedure car:
ERROR: In procedure car: Wrong type (expecting pair): ()

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [3]> ")
  signal(error ("Error in evaluating guile expression: ERROR: In procedure car:\nERROR: In procedure car: Wrong type (expecting pair): ()\n\nEntering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.\nscheme@(guile-user) [3]> "))
  error("Error in evaluating guile expression: %s" "ERROR: In procedure car:\nERROR: In procedure car: Wrong type (expecting pair): ()\n\nEntering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.\nscheme@(guile-user) [3]> ")
  (if (geiser-eval--retort-error res) (error "Error in evaluating guile expression: %s" (geiser-eval--retort-output res)) (cdr (assq (quote result) res)))
  (let ((res (geiser-eval--send/wait (list (quote :eval) (list (quote :scm) str))))) (if (geiser-eval--retort-error res) (error "Error in evaluating guile expression: %s" (geiser-eval--retort-output res)) (cdr (assq (quote result) res))))
  (save-current-buffer (set-buffer (or repl (guix-geiser-repl))) (let ((res (geiser-eval--send/wait (list (quote :eval) (list (quote :scm) str))))) (if (geiser-eval--retort-error res) (error "Error in evaluating guile expression: %s" (geiser-eval--retort-output res)) (cdr (assq (quote result) res)))))
  guix-geiser-eval("(package-location-string \"foo\")" #<buffer *Guix Internal REPL*>)
  (car (guix-geiser-eval str repl))
  (replace-regexp-in-string "#t" "t" (car (guix-geiser-eval str repl)))
  (replace-regexp-in-string "#f\\|#<unspecified>" "nil" (replace-regexp-in-string "#t" "t" (car (guix-geiser-eval str repl))))
  (read (replace-regexp-in-string "#f\\|#<unspecified>" "nil" (replace-regexp-in-string "#t" "t" (car (guix-geiser-eval str repl)))))
  guix-geiser-eval-read("(package-location-string \"foo\")" #<buffer *Guix Internal REPL*>)
  guix-eval-read("(package-location-string \"foo\")")
  guix-package-location("foo")
  eval((guix-package-location "foo") nil)
  eval-expression((guix-package-location "foo") nil)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)
--8<---------------cut here---------------end--------------->8---

I think this patch fixes it:

diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
index 34da6ac..c5d5d75 100644
--- a/emacs/guix-main.scm
+++ b/emacs/guix-main.scm
@@ -954,10 +954,14 @@ GENERATIONS is a list of generation numbers."
 
 (define (package-location-string id-or-name)
   "Return a location string of a package with ID-OR-NAME."
-  (and-let* ((package  (or (package-by-id id-or-name)
-                           (first (packages-by-name id-or-name))))
-             (location (package-location package)))
-    (location->string location)))
+  (define package
+    (or (package-by-id id-or-name)
+        (match (packages-by-name id-or-name)
+          (() #f)
+          ((first . rest) first))))
+
+  (and package
+       (location->string (package-location package))))
 
 (define (package-source-derivation->store-path derivation)
   "Return a store path of the package source DERIVATION."

Thoughts?

Ludo’.