So most of the time, Nix is placing the files exactly like in a normal FHS distribution, except that it prefixes the path with /nix/store/somehash-somename/
(with equals $out
at build time), and that it strips some paths. For instance since in FHS distributions, /usr/
and /usr/local
are containing basically the same structure as /
for programs installed by users (which is not needed in nix), nix will remove the /usr
and /usr/local
prefixes. This is quite practical, since this way nix can simply set $PREFIX=/nix/store/somehash-somename/
(that is often set by default to /usr/local
) and run as-it most existing auto-tools/cmake/make scripts.
In particular, since in normal FHS distributions man pages are located in /usr/share/man
, in nix we just need to install man pages in $out/share/man
.
Now, to solve your specific problem, the hardest part is actually to understand how git is finding the documentation of its commands. Since you mention the git diff
command, let's inspect the git folder to find out where it stores the documentation files:
$ nix-build -E 'let pkgs = import <nixpkgs> {}; in pkgs.gitFull'
/nix/store/hvl0fxxkva3ql9ksiy8p8pl3cxli24l8-git-with-svn-2.39.0
$ cd /nix/store/hvl0fxxkva3ql9ksiy8p8pl3cxli24l8-git-with-svn-2.39.0
# fd is a really cool tool to quickly search files based on their name
$ fd diff
…
share/man/man1/git-diff.1.gz
…
Bingo, it seems like the documentation is a simple man
file. Actually, if we run:
$ git help mytest
No manual entry for gitmytest
it seems like git directly runs man gitmytest
(not sure why there is no dash involved here anymore…), and this seems to work even if mytest
is not an existing git command. So we just need to create a man entry for gitmytest
!
For this, let's create this template in a new file git-mytest
(obtained by just googling how to create a man page):
.\" Manpage for git mytest.
.TH man 1 "06 May 2010" "1.0" "git mytest man page"
.SH NAME
git mytest \- test to document random git commands
.SH SYNOPSIS
git mytest [USERNAME]
.SH DESCRIPTION
git mytest is a non-existing command that I use to do some tests.
.SH OPTIONS
Since it does not even exists, there is little chance it has options.
.SH SEE ALSO
useradd(8), passwd(5), nuseradd.debian(8)
.SH BUGS
No known bugs.
.SH AUTHOR
Tobias Bora (t@b.com)
Then, we just need to create a basic package to install this. Note that there is no need to override gitFull
, we can just create a new package to install it in a separate package. In my tests, I will be using a default.nix
file containing:
{ pkgs ? import <nixpkgs> {} }:
pkgs.stdenv.mkDerivation {
name = "git-mytest";
src = ./.;
buildPhase = "";
installPhase = ''
mkdir -p $out/share/man/man1
cp $src/git-mytest $out/share/man/man1/gitmytest.1
'';
}
We can build it and check if the file has been produced correctly:
$ nix-build
$ ls ./result/share/man/man1
gitmytest.1.gz
Cool, nix has even compressed it for us. To double check the content is the good one, you can run zcat ./result/share/man/man1/gitmytest.1.gz
and it will print the uncompressed file.
Now, it is time to try it. One solution is to directly install it system-wide, either by inserting the above derivation in your configuration.nix
or else where. But for the testing purposes, I wanted to avoid to install it globally, so I just created a shell.nix
that loads the package that we just created:
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
let mantest = import ./default.nix { inherit pkgs; }; in
pkgs.mkShell {
packages = [ mantest ];
buildInputs = [ ];
shellHook = ''
echo "Exporting manpage path"
export MANPATH=${mantest}/share/man:$MANPATH
'';
}
You can see that I added a shellHook
: this line is actually needed only for this test in order to specify to man
where it should look for the man pages. But once you actually install the program, this will not be needed anymore.
Then, just load the shell and test it:
$ nix-shell
$ git help mytest
# you should get the man page printed!
It works! Enjoy ;-)
EDIT
Ok, so it seems like the above instructions do not work if an alias is created, in which case the message is always the same myalias is aliased to XXX
. This comes from this line in the code and seems impossible to avoid directly. However, instead of creating an alias, you can simply create a new git plugin (and if you need to document it, chances are that it might make sense to create one), i.e. a binary file called git-mytest
(when running git mytest
, git will automatically run git-mytest
). git-mytest
can be a simple bash script calling git directly. This can be done as follows (note that this time you need to write the hypens in the man page, it seems that it attributes different man page names depending on the type of command):
{ pkgs ? import <nixpkgs> {} }:
pkgs.stdenv.mkDerivation {
name = "git-mytest";
src = ./.;
buildPhase = "";
installPhase = ''
mkdir -p $out/share/man/man1
mkdir -p $out/bin
# "git mytest" will run "git-mytest", so we just need to create a binary called "git-mytest"
# (nix will automatically patch /bin/bash, so it's fine to use here, the "$@$ in the bash forwards the argument to the command)
echo '#!/bin/bash' > $out/bin/git-mytest
echo 'git log --all --graph "$@"' >> $out/bin/git-mytest
chmod +x $out/bin/git-mytest
# Installs the documentation for the command
# this time, if the command exists, you do need a "-"
cp $src/git-mytest $out/share/man/man1/git-mytest.1
'';
}
just replace the above default.nix
file above with this, and run again nix-shell
. Then, you should be good to type:
$ git mytest
# runs git log --all --graph
$ git help mytest
prints the man page
$ git mytest -h
Prints the help of "git log" since for now we forward the arguments.
If you want "git mytest -h" to print a different message, just search for "-h" in the arguments in the bash script and run for instance "man git-mytest" yourself.
/nix/store
rather than spread around the filesystem. So a solution for Ubuntu is unlikely to work for Nix in this case. – l0b0 Nov 13 '23 at 06:36