feat(nix): Support package set imports from different sources

This extends the package set import mechanism in
build-registry-image.nix with several different options:

1. Importing a nixpkgs channel from Github (the default, pinned to
   nixos-19.03)

2. Importing a custom Nix git repository. This uses builtins.fetchGit
   and can thus rely on git/SSH configuration in the environment (such
   as keys)

3. Importing a local filesystem path

As long as the repository pointed at is either a checkout of nixpkgs,
or nixpkgs overlaid with custom packages this will work.

A special syntax has been defined for how these three options are
passed in, but users should not need to concern themselves with it as
it will be taken care of by the server component.

This relates to #3.
This commit is contained in:
Vincent Ambo 2019-07-31 01:45:09 +01:00 committed by Vincent Ambo
parent a83701a14b
commit 2db92243e7

View file

@ -34,14 +34,66 @@
# plenty of room for extension. I believe the actual maximum is
# 128.
maxLayers ? 24,
# Nix channel to use
channel ? "nixos-19.03"
# Configuration for which package set to use when building.
#
# Both channels of the public nixpkgs repository as well as imports
# from private repositories are supported.
#
# This setting can be invoked with three different formats:
#
# 1. nixpkgs!$channel (e.g. nixpkgs!nixos-19.03)
# 2. git!$repo!$rev (e.g. git!git@github.com:NixOS/nixpkgs.git!master)
# 3. path!$path (e.g. path!/var/local/nixpkgs)
#
# '!' was chosen as the separator because `builtins.split` does not
# support regex escapes and there are few other candidates. It
# doesn't matter much because this is invoked by the server.
pkgSource ? "nixpkgs!nixos-19.03"
}:
# Import the specified channel directly from Github.
let
channelUrl = "https://github.com/NixOS/nixpkgs-channels/archive/${channel}.tar.gz";
pkgs = import (builtins.fetchTarball channelUrl) {};
# If a nixpkgs channel is requested, it is retrieved from Github (as
# a tarball) and imported.
fetchImportChannel = channel:
let url = "https://github.com/NixOS/nixpkgs-channels/archive/${channel}.tar.gz";
in import (builtins.fetchTarball url) {};
# If a git repository is requested, it is retrieved via
# builtins.fetchGit which defaults to the git configuration of the
# outside environment. This means that user-configured SSH
# credentials etc. are going to work as expected.
fetchImportGit = url: rev:
let
# builtins.fetchGit needs to know whether 'rev' is a reference
# (e.g. a branch/tag) or a revision (i.e. a commit hash)
#
# Since this data is being extrapolated from the supplied image
# tag, we have to guess if we want to avoid specifying a format.
#
# There are some additional caveats around whether the default
# branch contains the specified revision, which need to be
# explained to users.
spec = if (builtins.stringLength rev) == 40 then {
inherit url rev;
} else {
inherit url;
ref = rev;
};
in import (builtins.fetchGit spec) {};
importPath = path: import (builtins.toPath path) {};
source = builtins.split "!" pkgSource;
sourceType = builtins.elemAt source 0;
pkgs = with builtins;
if sourceType == "nixpkgs"
then fetchImportChannel (elemAt source 2)
else if sourceType == "git"
then fetchImportGit (elemAt source 2) (elemAt source 4)
else if sourceType == "path"
then importPath (elemAt source 2)
else builtins.throw("Invalid package set source specification: ${pkgSource}");
in
# Since this is essentially a re-wrapping of some of the functionality that is