[Nix-dev] string vs path hell
Sergey Mironov
grrwlf at gmail.com
Tue Jun 10 13:45:38 CEST 2014
Wow, Nix strings are not that simple at all. I'll now go and make my
own copy of splitString with '==' replaced by 'lib.eqSttring' as you
have suggested.
Thanks for the explanation!
Sergey
2014-06-10 13:27 GMT+04:00 Kirill Elagin <kirelagin at gmail.com>:
> 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
>>>>
>>>>
>>>
>>
>
More information about the nix-dev
mailing list