Reputation: 263
Is there a way to remove a config file from a fetchFromGitHub? I’d like to replace the default config with my own config. So far all of the files from the repo are built and symlinked into ".config/yazelix", but none of the postFetch commands have been ran. Everything builds without any errors.
I've added the following to the home.file
section of my "home.nix" file:
".config/yazelix".source = pkgs.fetchFromGitHub {
owner = "luccahuguet";
repo = "yazelix";
rev = "1093c18c22d9d9858f4cf5813bd9aa7578660af8";
hash = "sha256-+6Mq8mR/tF1Z+GyooMz9fWGV57bFhbHXBVBDkHpUMDA="; # build and get the hash from the error
postFetch = ''
rm $out/zellij/config.kdl
cp ./apps/yazelix/config.kdl $out/zellij/config.kdl
'';
};
Does anyone have any suggestions to get this to work? Any help is greatly appreciated.
Upvotes: 2
Views: 163
Reputation: 1261
Let me follow up with a bit of a deeper explanation as to why this is happening.
When Nix evaluates a derivation, it first checks if there is a corresponding realisation of it in the store already. If one exists, it will skip every remaining step and simply use the path in the store in lieu of building the derivation again. This is because Nix is able to determine that the contents of the derivation itself has not changed, therefore the derivation doesn't need to be updated.
fetchFromGitHub
is an even more special derivation besides that. It is what we refer to as a fixed-output derivation, which forces a check of the output contents to a hash to ensure consistency. These are commonly used as downloaders to pull sources from the internet and guarantee consistency via the hash. This hash is set as part of the fetcher's attributes.
Why is this a problem? Well, Nix will use this hash to determine if there is a valid store path of this derivation. If one exists, Nix will immediately use that instead of rebuilding (or in this case refetching) the contents. See why this is a problem? Your postFetch
is ignored after every new change unless you also invalidate the hash each time.
Someone pointed out that the issue may be my path in the cp command, since the nix build environment is sandboxed. After correcting my path, as shown below, and updating my hash, everything was working as it should.
Too early to celebrate! You've only managed to get it working thanks to invalidating the hash. It had nothing to do with switching your path here. Try pushing a new revision update to the repo or even changing your config and you'll see that neither action affects the derivation on your system at all. Nix can find the old derivation because the hash hasn't been invalidated, so it immediately uses it instead.
Furthermore, you do not need a fancy mkDerivation
wrapper as suggested in another answer. It's perfectly acceptable, but unnecessary. The only important thing is correctly invalidating the hash.
A simpler derivation you can write (assuming you aren't updating this GitHub repo that much on its own), is to use a bare bones runCommandNoCC
:
runCommandNoCC "my-config" {
src = fetchFromGitHub { ... };
} ''
mkdir -p $out/zellij
cp ${./path/to/your/config.kdl} $out/zellij/config.kdl
cp --no-clobber --recursive --target $out $src/*
''
This little derivation will automatically determine that your file has changed during evaluation and will automatically replace it each time. You can FURTHER optimize this by using a symlinkJoin
to avoid copying so many files everywhere (instead it uses symlinks), which you can do at your own discretion.
Upvotes: 1
Reputation: 263
Someone pointed out that the issue may be my path in the cp
command, since the nix build environment is sandboxed. After correcting my path, as shown below, and updating my hash, everything was working as it should.
".config/yazelix".source = pkgs.fetchFromGitHub {
owner = "luccahuguet";
repo = "yazelix";
rev = "1093c18c22d9d9858f4cf5813bd9aa7578660af8";
hash = ""; # build and get the hash from the error
postFetch = ''
rm $out/zellij/config.kdl
cp ${./apps/yazelix/config.kdl} $out/zellij/config.kdl
'';
};
Passing the relative path/file in as a variable, in the postFetch
, allows it to be used in the sandboxed build environment. There may be other ways of doing this, but this technique is working and is fairly elegant.
Upvotes: 0
Reputation: 385
The postFetch
snippet you provided should work fine.
I think the issue is that source = pkgs.fetchFromGithub
looks for the hash
to update the store entry. If you have built a first generation without postFetch
, Home Manager won't rebuild automatically the store entry after you add or edit the postFetch
phase.
To force the update, you should delete the store entry and rebuild your home configuration following these steps:
".config/yazelix".source
and build a new home configuration generation. This is needed to remove the dependency on the Nix store, otherwise you won't be able to delete the entry.home-manager remove-generation <id>
. You can find the id
with home-manager generations
.nix-store --delete <path>
. You can find the path
with ls -dl ~/.config/yazelix
.".config/yazelix".source
and build a new home configuration generationThe manual method is not future-proof as you'll need to apply it again each time you edit config.kdl
. An alternative is to create a derivation:
file = let
myConfig = pkgs.stdenv.mkDerivation {
name = "custom-yazelix-config";
src = pkgs.fetchFromGitHub {
owner = "luccahuguet";
repo = "yazelix";
rev = "1093c18c22d9d9858f4cf5813bd9aa7578660af8";
hash = "sha256-+6Mq8mR/tF1Z+GyooMz9fWGV57bFhbHXBVBDkHpUMDA=";
};
installPhase = ''
mkdir -p $out/zellij
cp ${self}/apps/yazelix/config.kdl $out/zellij/config.kdl
'';
};
in {
".config/yazelix".source = myConfig;
};
Here ${self}
is the path of the flake providing the home configuration.
Upvotes: 2