Pádraig Brady <[email protected]> writes:

> This patch set adds --env0-from to the env(1) command.
>
> https://github.com/pixelb/coreutils/compare/env0-from
>
> This supports efficient round tripping from the output of `env -0`,
> which may contain non standard environment entries without '=' etc.
>
> Note the naming was chosen to be descriptive and consistent form
> with the existing --files0-from option in various commands.
>
> The trigger for doing this now was the request to support regex filtering
> of environment entries, which can now be achieved more generally
> and robustly with something like:
>
>   env -i --env0-from=<( env -0 | sed -z ... )
>
> For textual environment files, one can leverage sh to parse and exec,
> which gives support for comments, interpolation etc. which there
> is no need for env(1) to re-implement, though a subset of that
> functionality is available through the -S option if required.

Nice, it works well with more environment variables than you could ever need:

    $ for i in {0..50000}; do export ENV$i=$i; done
    $ env -0 > .env
    $ time ./src/env -i --env0-from=<(cat $(yes .env | head -n 1000)) \
        >/dev/null
    real    0m15.132s
    user    0m14.314s
    sys     0m1.159s

Some minor things:

+/* Return true if ENTRY is an assignment whose name is NAME.  */
+static bool
+entry_has_name (char const *entry, char const *name, idx_t name_length)
+{
+  char const *eq = strchr (entry, '=');
+  return (eq && eq - entry == name_length
+          && memcmp (entry, name, name_length) == 0);
+}

It's probably better to use memeq for consistency:

    $ git grep --perl-regexp 'memcmp *\(\S+?, *\S+?, *\S+?\) == 0' | wc -l
    1
    $ git grep --perl-regexp 'memeq *\(\S+?, *\S+?, *\S+?\)' | wc -l
    11

+/* Hash an environment vector slot by the name in its assignment.  */
+static size_t
+env_vector_slot_hash (void const *x, size_t table_size)
+{
+  char *const *slot = x;
+  char const *entry = *slot;
+  char const *eq = strchr (entry, '=');
+  size_t value = 0;
+  for (char const *p = entry; p < eq; ++p)
+    value = value * 31 + (unsigned char) *p;
+  return value % table_size;
+}

I was going to say we could just use lib/hashcode-string1.c, but I guess
Gnulib doesn't have a function for hashing N bytes of memory instead of
NUL terminated strings. I would have thought we had a need for it
somewhere.

Collin

Reply via email to