[Nix-dev] string vs path hell

Kirill Elagin kirelagin at gmail.com
Tue Jun 10 11:27:57 CEST 2014


So, here is what I found.

Strings in nix have contexts:
https://github.com/NixOS/nix/blob/master/src/libexpr/value.hh#L45.
When you compare strings with  `==`, those contexts also get compared.

So, `lib.splitString`, obviously, uses `==` internally to compare
substrings with the separator, and since `"/"` doesn't have any context the
comparison will never yield true.

I'm not really sure what is the proper workaround here. I guess, in your
case this might be the right thing to do:

~~~
nix-repl> lib.splitString "/" a
[ "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar" ]

nix-repl> lib.splitString "/" (builtins.unsafeDiscardStringContext a)
[ "" "nix" "store" "nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1" "foo"
"bar" ]
~~~

Another option is changing `splitString` to use `lib.eqString` which
basically concatenates contexts before doing `==`. But I'm not sure, that
might break something.

So, as another workaround, you can concatenate the contexts yourself:

~~~
nix-repl> lib.splitString "/" a
[ "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar" ]

nix-repl> lib.splitString (lib.substring 0 0 a + "/") a
[ "" "nix" "store" "nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1" "foo"
"bar" ]
~~~


--
Кирилл Елагин


On Tue, Jun 10, 2014 at 1:11 PM, Kirill Elagin <kirelagin at gmail.com> wrote:

> Going further:
>
> ~~~~~~~~~~~
> nix-repl> a = "${pkgs.busybox}/foo/bar"
>
> nix-repl> b =
> "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar"
>
> nix-repl> a
> "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar"
>
> nix-repl> b
> "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar"
>
> nix-repl> lib.substring 0 1 a
> "/"
>
> nix-repl> lib.substring 0 1 b
> "/"
>
> nix-repl> lib.substring 0 1 a == "/"
> false
>
> nix-repl> lib.substring 0 1 b == "/"
> true
> ~~~~~~~~~~~~~
>
>
> --
> Кирилл Елагин
>
>
> On Tue, Jun 10, 2014 at 1:04 PM, Kirill Elagin <kirelagin at gmail.com>
> wrote:
>
>> Oh yeah, I've managed to reproduce this:
>>
>> ~~~~~
>> nix-repl> :l <nixpkgs>
>> Added 3863 variables.
>>
>> nix-repl> lib.splitString "/" "${pkgs.busybox}/foo/bar"
>> [ "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar" ]
>>
>> nix-repl> lib.splitString "/" (toString "${pkgs.busybox}/foo/bar")
>> [ "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar" ]
>>
>> nix-repl> lib.splitString "/"
>> "/nix/store/nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1/foo/bar"
>> [ "" "nix" "store" "nn00kn1fa0154qa1szszijw825cha8ps-busybox-1.22.1"
>> "foo" "bar" ]
>> ~~~~~
>>
>> Total weirdness.
>>
>>
>> --
>> Кирилл Елагин
>>
>>
>> On Tue, Jun 10, 2014 at 12:58 PM, Kirill Elagin <kirelagin at gmail.com>
>> wrote:
>>
>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> let lib = (import <nixpkgs> {}).lib;
>>>     exe = {
>>>       foo = "/some/path/to/foo";
>>>       bar = "/other/path/to/bar";
>>>     };
>>> in
>>> {
>>>   contents =
>>>
>>>     map (v :
>>>       let
>>>         takeFileName = p :
>>>           let fl = lib.splitString "/" p; in lib.last fl;
>>>         fn = takeFileName "${v}";
>>>         dummy = takeFileName "/a/string/encoded/path/dummy";
>>>       in
>>>
>>>         #builtins.trace fn
>>>         #builtins.trace dummy
>>>
>>>
>>>         {
>>>           symlink = "/bin/${fn}";
>>>           object = v;
>>>         }) (lib.attrValues exe);
>>> }
>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>
>>> ~~~~~~~~~~~~~~~~
>>> nix-repl> :l test.nix
>>> Added 1 variables.
>>>
>>> nix-repl> :p contents
>>> [ { object = "/other/path/to/bar"; symlink = "/bin/bar"; } { object =
>>> "/some/path/to/foo"; symlink = "/bin/foo"; } ]
>>> ~~~~~~~~~~~~~~~~~
>>>
>>> Dunno, you should probably inspect your `exe` set closer in case
>>> something's wrong with values there.
>>>
>>>
>>> --
>>> Кирилл Елагин
>>>
>>>
>>> On Tue, Jun 10, 2014 at 10:41 AM, Sergey Mironov <grrwlf at gmail.com>
>>> wrote:
>>>
>>>> OK, you are right. My code snippet really works fine. So I feel I must
>>>> post a part of my real code which still doesn't work for me. It is a
>>>> bit long, but maybe you will be able to help me find a mistake. Here
>>>> it is (below). This expression takes a set of paths to the executables
>>>> (exe // setuids) and builds the initrd image. Every attribute of (exe
>>>> // setuids) is either a string like [adduser =
>>>> "${busybox}/sbin/adduser";] or the result of mkDerivation producing
>>>> the single binary in it's $out.
>>>>
>>>> Note the "dummy" expression. If I uncomment "builtins.trace dummy"
>>>> line, it will show me the expected result (string "dummy" for every
>>>> list item). But in the same time, "builtins.trace fn" shows that fn is
>>>> evaluated incorrectly. Every time it contains full Nix path
>>>> ("/nix/strote/...", see example at the end of the letter) instead of
>>>> the filename part. It looks like 'splitString' doesn't recognize it's
>>>> argument as a string.
>>>>
>>>> Please, comment!
>>>> Sergey
>>>>
>>>>
>>>> --
>>>> the code
>>>>
>>>>       ...
>>>>
>>>>       img = makeInitrd {
>>>>
>>>>         compressor = "${gzip}/bin/gzip --fast";
>>>>
>>>>         contents = with all.ipkgs;
>>>>           [{ symlink = "/init";
>>>>             object = exe.init;
>>>>           }
>>>>           { symlink = "/bin/sh";
>>>>             object = exe.shell;
>>>>           }] ++
>>>>           map (v :
>>>>
>>>>             let
>>>>
>>>>               takeFileName = p : let
>>>>                   fl = lib.splitString "/" p;
>>>>                 in lib.last fl;
>>>>
>>>>               fn = takeFileName "${v}";
>>>>
>>>>               dummy = takeFileName "/a/string/encoded/path/dummy";
>>>>
>>>>             in
>>>>
>>>>             # builtins.trace fn   # <---------------- see example
>>>> output below
>>>>             # builtins.trace dummy
>>>>
>>>>             {
>>>>               symlink = "/bin/${fn}";
>>>>               object = v;
>>>>             }) (lib.attrValues (exe // setuids));
>>>>       };
>>>>
>>>> --
>>>> example output of "builtins.trace fn":
>>>>
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/sbin/addgroup
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/sbin/adduser
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/false
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/true
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/awk
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/cat
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/chmod
>>>> trace:
>>>> /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/chown
>>>> trace: /nix/store/sx19dvnv3wi2j8pvyra8npl9vdwdbmrk-busybox-1.21.1/bin/cp
>>>> trace:
>>>> /nix/store/h8rs91fjivsh6wakmwmpkca31wfp38g0-msr-tools-1.3/bin/cpuid
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.science.uu.nl/pipermail/nix-dev/attachments/20140610/d9ed2e5c/attachment.html 


More information about the nix-dev mailing list