Better error message when staging a file into a not-directory

Background

I had an incident the other day where I was staging a file into a directory, but one of the directory components was in fact a file and not a directory.

This is because I had created some configuration files to install into /etc/pam.d in a lower level dependency, but I had forgotten to add a line to say mkdir -p %{install-root}/etc/pam.d, which means my install invocations ended up installing all of my config files as /etc/pam.d instead of installing them as /etc/pam.d/system-auth, /etc/pam.d/user-auth etc.

When I encountered the error, it was because another element higher in the stack also wanted to install a pam config file, and when staging these elements together I got an error like this:

Failed to remove destination file: '/home/tristan/.cache/buildstream/build/<tempdir>/root/etc/pam.d/system-auth': Not a directory

This is a confusing and misleading error, here we are doing our safe install instead of copy semantic of always removing a file before creating it, and the /etc/pam.d directory was a file.

A nicer error message would be something like:

Failed to replace '/etc/pam.d/system-auth' while installing the file: one of the leading path components is not a directory

Task description

  • Use sandbox relative paths when communicating a failure inside the sandbox. We should only really use host paths when reporting an irrecoverable error, but not when it is a failure inside the sandbox which the user can clearly fix.
  • Explain the ENOTDIR error more clearly to the user, especially when removing the file this is not a clearly expressed error message.