gregwebs/Shelly.hs

case-insensitive environment variable handling on Windows breaks in bash

hsenag opened this issue · 6 comments

Since 9371a18, environment variable names on Windows are converted to lower-case. This breaks code that sets upper-case environment variables and then calls a bash script - it seems bash on Windows (in msys) is still able to distinguish case. For example before the change this code worked:

Main.hs:

     {-# LANGUAGE OverloadedStrings #-}
    module Main where

    import Shelly

    main :: IO ()
    main = shelly $ do
      setenv "WIBBLE" "upper"
      setenv "wibble" "lower"
      run "bash" ["go.sh"]

go.sh:

    #!/bin/sh

    echo WIBBLE: $WIBBLE
    echo wibble: $wibble

working output:

WIBBLE: upper
wibble: lower

broken output:

WIBBLE:
wibble: lower

CC @eric-corumdigital

BTW the example is intended to show that case-sensitivity works with bash on Windows - I'm not actually trying to use both cases at the same time. The problem is that I'm using the upper-case variable names in both the code and the shell script, in code that runs on both Windows and Linux. To make this code work again portably I'd have to use lower-case environment variable names everywhere, which would be quite unnatural.

As you have demonstrated, there are unix-like programs used by Windows developers which are case sensitive. I sent in this patch because Shelly was not working with programs which depend on case insensitivity, and case insensitivity is the norm on Windows.

The normalisation is arbitrary and could be changed to uppercase. This may incidentally resolve some incompatibilities. Overall, though, it is not my understanding that Shelly is supposed to be portable. Whether my understanding is correct is a question for the creator.

My belief is that shelly should support writing portable code. It uses Haskell libraries for file system manipulation that are portable.

However, I don't think it is possible to write portable code that assumes case insensitivity. I think my preference would be to revert the change and turn this into a feature that can be optionally turned on or off at runtime.

It should be trivial then to write a function that will turn it on for Windows.

Then every function which makes use of environment variables must take an additional configuration argument. Or maybe Sh should be a Reader of this option.

You could use a mutable variable but that is not well aligned with a functional spirit.

Yes, add to the existing state (actually Reader IORef) monad