Fetchgit doesn't seem to work for the local filesystem

I have cases in which I want to be able to install things from my local git repositories, things that aren’t published. It appears that fetchgit is supposed to work with those, but for some reason it doesn’t.

Given this directive:

  src = fetchgit {
    url = "/home/savanni/src/luminescent-dreams";
    rev = "3d93c8bae3ed9a5102f80b79b67a82451bd65ba8";
    sha256 = "166ia73vrcl5c9hm4q1a73qdn56m0jc7flfsk5p5q41na9f10lb0";
  };

the output that I get from running nix-env -i is:

building '/nix/store/qbawazd4iv4sljrqhfh18lxdzscw0sqj-luminescent-dreams.drv'...
exporting /home/savanni/src/luminescent-dreams (rev sol) into /nix/store/348k1k4prwgh6rwdv22nqv218785n2wh-luminescent-dreams
Initialized empty Git repository in /nix/store/348k1k4prwgh6rwdv22nqv218785n2wh-luminescent-dreams/.git/
fatal: '/home/savanni/src/luminescent-dreams' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: '/home/savanni/src/luminescent-dreams' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: '/home/savanni/src/luminescent-dreams' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

This is very strange, because it looks like the fetcher for fetchgit is a script nix-prefetch-git, which actually does work if I run it manually:

[] savanni@garnet:~/s/ld2 $ ~/src/nixpkgs/pkgs/build-support/fetchgit/nix-prefetch-git --no-deepClone --out . --url /home/savanni/src/luminescent-dreams --rev 3d93c8bae3ed9a5102f80b79b67a82451bd65ba8

This clones the repository as I expect, though not into my specified --out directory:

Initialized empty Git repository in /tmp/git-checkout-tmp-XX318smq/luminescent-dreams-3d93c8b/.git/
remote: Enumerating objects: 171, done.
remote: Counting objects: 100% (171/171), done.
remote: Compressing objects: 100% (151/151), done.
remote: Total 171 (delta 5), reused 98 (delta 3)
Receiving objects: 100% (171/171), 439.35 KiB | 39.94 MiB/s, done.
Resolving deltas: 100% (5/5), done.
From /home/savanni/src/luminescent-dreams
 * branch            HEAD       -> FETCH_HEAD
Switched to a new branch 'fetchgit'
removing `.git'...

git revision is 3d93c8bae3ed9a5102f80b79b67a82451bd65ba8
path is /nix/store/klfxwqb8pqfvjh536xyyffaw8qavynl3-luminescent-dreams-3d93c8b

So, I don’t actually understand where that error message comes from. Do any of you have any pointers as to how I’m using fetchgit incorrectly, or where I can dig to diagnose this?

I can’t see any examples of fetchgit that use anything but url (https or git://).

There is however a fetchgitlocal , that might work with filesystem paths?

Well, that yields more data. fetchgitlocal also doesn’t work:

[] savanni@garnet:~/.nixpkgs (sol *) $ nix-env -f fitnesstrax/ft.nix -i
installing 'fitnesstrax-gtk'
building '/nix/store/72aj7jyajd1nywmxhrmy87gmd917pnmk-put-in-git.drv'...
/build/.attr-0: line 1: cd: /home/savanni/src/luminescent-dreams: No such file or directory
builder for '/nix/store/72aj7jyajd1nywmxhrmy87gmd917pnmk-put-in-git.drv' failed with exit code 1
error: build of '/nix/store/72aj7jyajd1nywmxhrmy87gmd917pnmk-put-in-git.drv' failed
(use '--show-trace' to show detailed location information)
[] savanni@garnet:~/.nixpkgs (sol *) $ cd /home/savanni/src/luminescent-dreams
direnv: loading ~/src/luminescent-dreams/.envrc
direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +GETTEXTDATADIRS +GSETTINGS_SCHEMAS_PATH +HOST_PATH +IN_NIX_SHELL +LD +MAGIC_DB +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST +NIX_BUILD_CORES +NIX_BUILD_TOP +NIX_CC +NIX_CC_WRAPPER_x86_64_unknown_linux_gnu_TARGET_HOST +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_STORE +NM +OBJCOPY +OBJDUMP +RANLIB +READELF +RUST_SRC_PATH +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +TEMP +TEMPDIR +TMP +TMPDIR +buildInputs +builder +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +name +nativeBuildInputs +nobuildPhase +out +outputs +patches +phases +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH
[] savanni@garnet:~/s/luminescent-dreams (sol *) $ 

Since fetchgitlocal thinks the directory doesn’t exist, and this looks a lot like the fetchgit error… maybe somehow the local filesystem isn’t actually available in the derivation?

Because, if I cut fetchgit and fetchgitlocal out, but keep the same path like so:

    src = /home/savanni/src/luminescent-dreams;

this builds just fine. I just don’t get to point to an exact revision.

Wondering… maybe a bare repository and .git file extension will work? I’ll try that next.

if you do a local path, don’t forget about lib.cleanSource

I never figured out what was wrong with the built-in fetchGitLocal, but I was able to write a version that works just fine for my own purposes.

let fetchGitLocal = { url, branch }: mkDerivation {
    name = "fetchGitLocal";
    inherit coreutils git url branch curl;
    builder = ./builder.sh;
  };
set -ue -o pipefail
source $stdenv/setup
declare -xp
export PATH="$coreutils/bin"
mkdir $out
cd $out
${git}/bin/git init
${git}/bin/git remote add origin $url
${git}/bin/git pull origin $branch
${git}/bin/git checkout $branch

Okay, this is cool. Unfortunately, totally stuck on other steps, but at least I can do this one.

2 Likes