From 7e839e383977394f43d4a28ab931964117e33995 Mon Sep 17 00:00:00 2001 From: Michael Alan Dorman Date: Sun, 1 May 2016 16:46:55 -0400 Subject: [PATCH 1/2] Demonstrate the problem with haskell-process-do-cabal. haskell-process-do-cabal has code that attempts to run cabal directly when there is no current interactive haskell process. Unfortunately, it doesn't work. This test demonstrates the problem, calling haskell-process-do-cabal and checking the *Messages* buffer for the presence of the string it should output if it was going to run cabal directly. Instead you get an error about the lack of a session associated with the buffer. --- tests/haskell-load-tests.el | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/haskell-load-tests.el b/tests/haskell-load-tests.el index 227f2e180..7331ecd58 100644 --- a/tests/haskell-load-tests.el +++ b/tests/haskell-load-tests.el @@ -2,6 +2,7 @@ ;;; Code: +(require 'cl) (require 'ert) (require 'haskell-test-utils) @@ -83,3 +84,14 @@ (search-forward "import Data.String") (haskell-goto-prev-error) (should (looking-at-p "Data.Mayb")))) + +(ert-deftest do-cabal-no-process () + "Ensure that haskell-process-do-cabal can call cabal directly. + +Redefine `shell-command' to just capture the command it's asked +to execute, and make sure it matches what we expected." + (let (shell-call) + (flet ((shell-command (command &optional input-buffer output-buffer) + (setq shell-call command))) + (haskell-process-do-cabal "help") + (should (equal shell-call "cabal help"))))) From 41532cf933b85a83da542e3af413930f629306cf Mon Sep 17 00:00:00 2001 From: Michael Alan Dorman Date: Sun, 1 May 2016 14:53:27 -0400 Subject: [PATCH 2/2] Fix logic for running cabal directly. I suspect this has been broken for a while (perhaps always). The failure stems from the fact that (haskell-interactive-process) throws an uncaught error if there is no interacive process, which aborts the function. If that is wrapped to mask the error, (process-status child) also throws an uncaught error, which aborts the function. Thus the direct cabal invocation code would never be reached. This is the least intrusive fix I can see---wrapping both calls with (ignore-errors), and not even checking (process-status) if we don't have a process. In manual testing it behaves as expected, running `cabal build`. A more extensive fix---which would rewrite the conditional logic to wrap all the dangerous bits in a single (ignore-errors)---would almost certainly swap positions of the indirect cabal invocation and the direct cabal invocation, so there would be much more churn. Still, it might produce a nicer overall result, if anyone wants to see that. --- haskell-load.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/haskell-load.el b/haskell-load.el index 3dd70c506..8bdfb0687 100644 --- a/haskell-load.el +++ b/haskell-load.el @@ -227,10 +227,12 @@ list of modules where missed IDENT was found." (defun haskell-process-do-cabal (command) "Run a Cabal command." - (let ((process (haskell-interactive-process))) + (let ((process (ignore-errors + (haskell-interactive-process)))) (cond - ((let ((child (haskell-process-process process))) - (not (equal 'run (process-status child)))) + ((or (eq process nil) + (let ((child (haskell-process-process process))) + (not (equal 'run (process-status child))))) (message "Process is not running, so running directly.") (shell-command (concat "cabal " command) (get-buffer-create "*haskell-process-log*")