Am I going about this the wrong way? Is it not allowed to add files to the $out directory during a build?
Edit: I just realized all files in the nix store (where $out points to) have 444 or 555 permission, so it makes sense that you can’t copy a file to a directory there. Then what is the correct way to package qutebrowser together with a custom script (additional file)?
> cp: cannot create regular file './misc/userscripts/qute-readlater': No such file or directory
I checked with nix develop 'nixkpgs#qutebrowser' + unpackPhase that the misc/userscripts directory really does exist. So I’m not sure what’s causing the above problem. Does the postUnpack run from inside the unpacked src archive?
Weird, this works just fine for me. What OS, Nix version and Nixpkgs revision do you use?
It runs from the /build directory inside the sandbox. The main body of unpackPhasesets sourceRoot variable but it is only cd’d into at the end of unpackPhase (after postUnpack).
$sourceRoot in postUnpack or later.
It depends on what is in the src attribute. fetchgit and derived fetchers like fetchFromGitHub use source, while archives fetched with fetchurl containing a single directory will just use the directory name as is.
Why did cp ${quteReadLater} "$out/share/..." fail with a permission denied error?
I don’t know yet.
Why did running this cp in the postUnpack hook instead work fine?
The file mode for the unpacked archive/directories has not yet been set. This makes sense since otherwise you couldn’t edit the source directory in any way, including by calling Make or patching, etc.
Is there a canonical way to refer to the source directory? The qutebrowser-2.5.4 format might break in the future.
From the unpackPhase function in stdenv.setup:
if [ -n "${setSourceRoot:-}" ]; then
runOneHook setSourceRoot
elif [ -z "$sourceRoot" ]; then
for i in *; do
if [ -d "$i" ]; then
case $dirsBefore in
*\ $i\ *)
;;
*)
if [ -n "$sourceRoot" ]; then
echo "unpacker produced multiple directories"
exit 1
fi
sourceRoot="$i"
;;
esac
fi
done
fi
If a single new directory is produced (as in the qutebrowser case), it is set to the variable sourceRoot.
What directory does the postUnpack hook canonically run from? Shouldn’t it run from the source root directory?
The answer to this is in the stdenv.setup shell script of nixpkgs. Specifically in the unpackPhase and genericBuild shell functions defined in this script.
Specifically, in genericBuild we have
eval "${!curPhase:-$curPhase}" #eval each phase (including unpackPhase)
# omitted lines
if [ "$curPhase" = unpackPhase ]; then
# make sure we can cd into the directory
[ -z "${sourceRoot}" ] || chmod +x "${sourceRoot}"
cd "${sourceRoot:-.}"
fi
So after unpackPhase + postUnpack hook runs, evaluation moves into the sourceRoot directory, which is where the files have been unpacked to.
Why is the unpack directory named source in @emmanuelrosa’s example, but qutebrowser-2.5.4 in my case? Isn’t the unpackPhase a standardized operation?
It is not standardized, except in that if the unpackPhase produces a single dir, the variable sourceRoot is set to that directory (relative file path).
Weird, does not look like there are any differences between the your commit and nixos-unstable I tried. We use the same Nix version as well. Maybe you are target of a curse or something.
Does the following give you any useful info?
final: prev:
{
qutebrowser = prev.qutebrowser.overrideAttrs (old: let
quteReadLater = ./qute-readlater;
in
{
postInstall = ''
ls -la "${quteReadLater}"
ls -la "$out/share/qutebrowser/userscripts"
cp ${quteReadLater} "$out/share/qutebrowser/userscripts/qute-readlater"
'' + old.postInstall;
});
}