Convert Path to list in main and preserve case#14764
Conversation
|
@fdncred While I'm confident that this is going to fix the |
|
My newly added tests are failing on Windows CI, so it looks like the conversion isn't working properly there. I'll test on Windows locally later. Moving to draft for now. |
|
I hate it when everything passes except one platform. It's such a pain. |
|
@fdncred It looks like these (new) failing tests might expose the problem you were having on Mac. Apparently the path conversion still wasn't case-insensitive as we thought, but we didn't have any test in place to cover that particular area. With the new tests in place, it fails, and that's a good thing, IMHO. Working on fixing it to make it truly case-insensitive now. |
|
"Case-insensitive" isn't the right word - I should get better about distinguishing "case-preserving". The problem here is that Again, the tests are now in place to catch this (which is what kept this one from going green until I got the real fix in). Can you give it another try? |
|
I still get the same thing on my mac when using my regular configuration. If I use This is what I have in my env.nu for ENV_CONVERSIONS. export-env {
let esep_list_converter = {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | str join (char esep) }
}
let esep_path_converter = {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | path expand | str join (char esep) }
}
$env.ENV_CONVERSIONS = {
PATH: $esep_path_converter
# Path: $esep_path_converter
LS_COLORS: $esep_list_converter
DYLD_FALLBACK_LIBRARY_PATH: $esep_path_converter
# PATHEXT: $esep_list_converter
# PSMODULEPATH: $esep_path_converter
}
} |
|
I have the same ENV_CONVERSIONS section on my Windows box, and $env.path (any text case) produces a list of paths on the latest main branch. This makes me wonder 2 things.
Also, one more tidbit. |
|
On Windows, with this PR, |
|
Hmm. I have a hunch, but I'll have to wait until this afternoon to see if it's on the right track. In the meantime, could you test without a path conversion in |
|
|
@Bahex I think I see the (or at least part of the) problem. #14591 seems to have the same problem I just fixed in Steps to reproduce: $env.foo = "foo"
$env.ENV_CONVERSIONS = {
foo: {
from_string: {|| '✅'}
to_string: {|| 'N/A'}
}
}
# Correct, since the case of the ENV_CONVERSION variable is the same:
print $"$env.foo should be ✅. $env.foo is ($env.foo)"
# => $env.foo should be ✅. $env.foo is ✅
# Also correct, since the lookup of $env.FOO should match case insensitive to $env.foo
print $"$env.FOO should be ✅. $env.FOO is ($env.FOO)"
# => $env.FOO should be ✅. $env.FOO is ✅
$env.bar = "❌"
$env.ENV_CONVERSIONS = {
BAR: {
from_string: {|| '✅'}
to_string: {|| 'N/A'}
}
}
# `bar` is not converted
print $"$env.bar should be ✅. $env.bar is ($env.bar)"
# => $env.bar should be ✅. $env.bar is ❌
# but `BAR` is a newly created variable by ENV_CONVERSIONS
print $"$env.BAR should be ✅. $env.BAR is ($env.BAR)"
# => $env.BAR should be ✅. $env.BAR is ✅This will be an issue if anyone has a Not 100% sure that's what @fdncred is running into, but it seems likely given the repro above. |
|
Ahh, just looked at the source code, I can see where I messed up, I do a case insensitive lookup, but store the new value with the key in |
|
@Bahex No worries! Obviously it took me a while to find the (same) issue in |
|
@fdncred Nice-to-have might be for |
|
@fdncred Ok, I think it's fixed for real this time. Can you throw your config at it to test? There's a chance that there's a breaking change here if you are setting an |
list in mainlist in main and preserve case
|
Still doesn't work but I think I figured out why based on your last comment, "or treating it as a string anywhere in your config". I have the ENV_CONVERSIONS set as above but what I didn't think about until you mentioned it, is I do this in my config.nu to get rid of any duplicate entries in my path. $env.PATH = ($env.PATH | par-each {|r| $r | split row (char esep)} | flatten | uniq | str join (char esep))If I remove that, it returns path as a list. However, shouldn't we be able to assign items to $env.PATH and have them still return a list without having to do a bunch of list creation/append/prepending? Another way of saying it is that I've used this for a long time and it just recently stopped working. I wonder if we should allow $env.path to be changed from a list to a different type. 🤔 |
In this case, you aren't modifying the list, though. You specifically convert it back from a str join (char esep)Once an environment variable is converted, there isn't anything in place to convert it again. Going back to 0.97.1 (before I started mucking about with it ;-):
Is it possible you just haven't been actively inspecting the type of Repro
let temp_home = (mktemp -d)
$env.XDG_CONFIG_HOME = $temp_home
$env.XDG_DATA_HOME = $temp_home
~/oldnu/nu-0.97.1-x86_64-unknown-linux-gnu/nu
# => No environment config file found at /tmp/tmp.r9CMRnZntc/nushell/env.nu
# => Would you like to create one with defaults (Y/n):
# =>
# => Environment config file created at: /tmp/tmp.r9CMRnZntc/nushell/env.nu
# => No config file found at /tmp/tmp.r9CMRnZntc/nushell/config.nu
# => Would you like to create one with defaults (Y/n):
# =>
# => Config file created at: /tmp/tmp.r9CMRnZntc/nushell/config.nu
# Banner __ ,
$env.PATH | first 5
# => ╭───┬────────────────────────────────────────╮
# => │ 0 │ /home/ntd/.local/share/rust/cargo/bin │
# => │ 1 │ /home/ntd/.local/share/rust/rustup/bin │
# => │ 2 │ /home/ntd/.config/carapace/bin │
# => │ 3 │ /home/ntd/.nix-profile/bin │
# => │ 4 │ /home/ntd/.nix-profile/bin │
# => ╰───┴────────────────────────────────────────╯
$env.PATH = ($env.PATH | par-each {|r| $r | split row (char esep)} | flatten | uniq | str join (char esep))
$env.PATH | str substring 0..100
# => /home/ntd/.local/share/rust/cargo/bin:/home/ntd/.local/share/rust/rustup/bin:/home/ntd/.config/carapa
$env.PATH | describe
# => string
Probably not. Or perhaps there should be logic to run It just doesn't seem that there's ever been any logic along those lines. |
You'd think that things wouldn't work right if it was just a string. Either way, I'm fine with landing this and seeing if anything else breaks. Good work researching and testing to figure out what was going on. |
I need to look up the code-path for that (to satisfy my own curiosity), but it seems to work fine as a string or a list: $env.PATH = "/usr/bin:/usr/sbin"
^ls
# => Works
nu
# => Fails, since cargo/bin is no longer in the path |
|
@fdncred Ah, we're using the |
|
|
|
Should be ready to land if it looks okay to everyone else. |
|
Thanks |


Description
Fixes multiple issues related to
ENV_CONVERSIONand path-conversion-to-list.convert_env_values(), but we found that this causednu -nto no longer convert the path properly.ENV_CONVERSIONShave apparently never preserved case, meaning a conversion with a key offoowould not update$env.FOObut rather create a new environment variable with a different case.PATH, but it only worked forPATHandPath.convert_env_values(), which handledENV_CONVERSIONSwas called in multiple places in the startup depending on flags.This PR:
main()rather than in each potential startup pathget_env_var_insensitive()functions added in add function to make env vars case-insensitive #14390 to return the name of the environment variable with its original case. This allows code that updates environment variables to preserve the case.ENV_CONVERSIONSto preserve the case of any updated environment variables. TheENV_CONVERSIONkey itself is still case insensitive.PATHenvironment variable (normally handled separately, regardless of whether or not there was anENV_CONVERSIONfor it).Before
env_convert_valueswas run:env.nuran, which includednu -c <commandstring>andnu <script.nu>nu -nAfter
env_convert_valuesalways runs once inmain()before any config file is processed or the REPL is startedUser-Facing Changes
Bug fixes
Tests + Formatting
toolkit fmttoolkit clippytoolkit testtoolkit test stdlibAdded additional tests to prevent future regression.
After Submitting
There is additional cleanup that should probably be done in
convert_env_values(). This function previously handledENV_CONVERSIONS, but there is no longer any need for this sinceconvert_env_vars()runs whenever$env.ENV_CONVERSIONSchanges now.This means that the only relevant task in the old
convert_env_values()is to convert thePATHto a list, and ensure that it is a list of strings. It's still calling thefrom_stringconversion on every variable (just once) even though there are noENV_CONVERSIONSat this point.Leaving that to another PR though, while we get the core issue fixed with this one.