[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [live-build] "E: Unable to find a source package for syslinux,grub-efi"



On Wed, 11 Mar 2020 at 05:52, <jnqnfe@gmail.com> wrote:
> On Tue, 2020-03-10 at 15:38 +0000, jnqnfe@gmail.com wrote:

> > obviously it seems to be treating "syslinux,grub-efi" as a single
> > package name which is wrong. this string originates from
> > LB_BOOTLOADERS.
> >
> > the code that should be handling this in source_debian looks to be
> > the
> > following:
> > ```
> > echo "${LB_BOOTLOADERS}" | \
> > while IFS="," read -r BOOTLOADER
> > do
> >       echo "${BOOTLOADER}" >> source-selection.txt
> > done
> > ```
> >
> > which is correctly specifying a comma as the separator, so if this is
> > where the problem originates, I don't know why...

Hi,

There's several issues to know about here.

First issue is that different shells, such as bash and dash, have
different syntax and behaviour. So this code must be tested in all
shells where it is expected to run.

Next issue is that the shell builtin command 'read' does not work the
way you seem to think. From the 'dash' manpage:
"""
  read [-p prompt] [-r] variable [...]

  [...] a line is read from the standard input. [...] and the line is
  split [...], and the pieces are assigned to the variables in order. At
  least one variable must be specified. If there are more pieces than
  variables, the remaining pieces (along with the characters in IFS that
  separated them) are assigned to the last variable.
"""
Demo code illustrating the final sentence I quoted there:

    printf '%s\n' "a1,a2,a3,a4" "b1,b2,b3,b4" | \
    while IFS="," read -r v1 v2 v3; do
        printf '%s\n' "v1:${v1} v2:${v2} v3:${v3}"
    done

The above demo code tested in 'dash' produces output:
v1:a1 v2:a2 v3:a3,a4
v1:b1 v2:b2 v3:b3,b4

Next issue is that there are subtle behaviour differences between
IFS='' and IFS unset. So those two states must be handled separately
when when modifying and restoring IFS

One approach is to use a subshell-function so that its local IFS can
be modified without affecting the IFS in the parent shell.

Demo code:

    mysubshell() (
        # use the IFS of this subshell-function to split $1 into $@
        IFS=,
        set -o noglob
        set -- $1
        set +o noglob
        for s in "$@" ; do echo "${s}" ; done
    )
    mysubshell a1,a2,a3,a4

The above demo code tested in 'dash' produces output:
a1
a2
a3
a4

But that requires a subshell.

To restore IFS state correctly without using a subshell involves
detecting when IFS is unset.

Demo code:

    # some test values for IFS
#    IFS=
#    unset IFS
#    IFS=foo

    # display IFS
    printf '%s' "IFS="
    /usr/bin/printf '%q' "${IFS-unset}"
    printf '\n'

    # remember IFS
    remember_ifs=${IFS-__flag__ifs-is-unset__}

    # change IFS for some purpose
    IFS=bar

    # restore IFS
    case "${remember_ifs}" in
        __flag__ifs-is-unset__ )
            # IFS was unset, so restore that state
            unset IFS
            ;;
        * )
            # restore the remembered value of IFS
            IFS=${remember_ifs}
            ;;
    esac

    # display IFS
    printf '%s' "IFS="
    /usr/bin/printf '%q' "${IFS-unset}"
    printf '\n'

The above demo code tested in 'dash' produces output:
initial IFS=' '$'\t\n'
restore IFS=' '$'\t\n'

That result is for the default value of IFS in 'dash'.
Uncomment various "test values for IFS" lines in the code
to demo how it handles those other initial values of IFS.


Reply to: