about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/bintools-wrapper/default.nix42
-rw-r--r--pkgs/build-support/docker/default.nix24
-rw-r--r--pkgs/build-support/docker/examples.nix25
-rw-r--r--pkgs/build-support/fetchgitea/default.nix7
-rw-r--r--pkgs/build-support/libredirect/libredirect.c81
-rw-r--r--pkgs/build-support/libredirect/test.c6
-rw-r--r--pkgs/build-support/rust/default.nix25
-rw-r--r--pkgs/build-support/rust/import-cargo-lock.nix167
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.lock83
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.toml8
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/basic/default.nix18
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/basic/src/main.rs9
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/default.nix8
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.lock79
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.toml8
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/default.nix21
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/src/main.rs9
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.lock79
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.toml8
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency/default.nix21
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/git-dependency/src/main.rs9
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/maturin/Cargo.lock682
-rw-r--r--pkgs/build-support/rust/test/import-cargo-lock/maturin/default.nix43
-rw-r--r--pkgs/build-support/vm/default.nix139
24 files changed, 1481 insertions, 120 deletions
diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix
index b2b47901981d..bf81d00e5ea7 100644
--- a/pkgs/build-support/bintools-wrapper/default.nix
+++ b/pkgs/build-support/bintools-wrapper/default.nix
@@ -9,10 +9,22 @@
 , lib
 , stdenvNoCC
 , bintools ? null, libc ? null, coreutils ? null, shell ? stdenvNoCC.shell, gnugrep ? null
+, netbsd ? null, netbsdCross ? null
+, sharedLibraryLoader ?
+  if libc == null then
+    null
+  else if stdenvNoCC.targetPlatform.isNetBSD then
+    if libc != targetPackages.netbsdCross.headers then
+      targetPackages.netbsdCross.ld_elf_so
+    else
+      null
+  else
+    lib.getLib libc
 , nativeTools, noLibc ? false, nativeLibc, nativePrefix ? ""
 , propagateDoc ? bintools != null && bintools ? man
 , extraPackages ? [], extraBuildCommands ? ""
 , buildPackages ? {}
+, targetPackages ? {}
 , useMacosReexportHack ? false
 
 # Darwin code signing support utilities
@@ -54,19 +66,19 @@ let
   # The dynamic linker has different names on different platforms. This is a
   # shell glob that ought to match it.
   dynamicLinker =
-    /**/ if libc == null then null
-    else if targetPlatform.libc == "musl"             then "${libc_lib}/lib/ld-musl-*"
+    /**/ if sharedLibraryLoader == null then null
+    else if targetPlatform.libc == "musl"             then "${sharedLibraryLoader}/lib/ld-musl-*"
     else if (targetPlatform.libc == "bionic" && targetPlatform.is32bit) then "/system/bin/linker"
     else if (targetPlatform.libc == "bionic" && targetPlatform.is64bit) then "/system/bin/linker64"
-    else if targetPlatform.libc == "nblibc"           then "${libc_lib}/libexec/ld.elf_so"
-    else if targetPlatform.system == "i686-linux"     then "${libc_lib}/lib/ld-linux.so.2"
-    else if targetPlatform.system == "x86_64-linux"   then "${libc_lib}/lib/ld-linux-x86-64.so.2"
-    else if targetPlatform.system == "powerpc64le-linux" then "${libc_lib}/lib/ld64.so.2"
+    else if targetPlatform.libc == "nblibc"           then "${sharedLibraryLoader}/libexec/ld.elf_so"
+    else if targetPlatform.system == "i686-linux"     then "${sharedLibraryLoader}/lib/ld-linux.so.2"
+    else if targetPlatform.system == "x86_64-linux"   then "${sharedLibraryLoader}/lib/ld-linux-x86-64.so.2"
+    else if targetPlatform.system == "powerpc64le-linux" then "${sharedLibraryLoader}/lib/ld64.so.2"
     # ARM with a wildcard, which can be "" or "-armhf".
-    else if (with targetPlatform; isAarch32 && isLinux)   then "${libc_lib}/lib/ld-linux*.so.3"
-    else if targetPlatform.system == "aarch64-linux"  then "${libc_lib}/lib/ld-linux-aarch64.so.1"
-    else if targetPlatform.system == "powerpc-linux"  then "${libc_lib}/lib/ld.so.1"
-    else if targetPlatform.isMips                     then "${libc_lib}/lib/ld.so.1"
+    else if (with targetPlatform; isAarch32 && isLinux)   then "${sharedLibraryLoader}/lib/ld-linux*.so.3"
+    else if targetPlatform.system == "aarch64-linux"  then "${sharedLibraryLoader}/lib/ld-linux-aarch64.so.1"
+    else if targetPlatform.system == "powerpc-linux"  then "${sharedLibraryLoader}/lib/ld.so.1"
+    else if targetPlatform.isMips                     then "${sharedLibraryLoader}/lib/ld.so.1"
     else if targetPlatform.isDarwin                   then "/usr/lib/dyld"
     else if targetPlatform.isFreeBSD                  then "/libexec/ld-elf.so.1"
     else if lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
@@ -224,10 +236,10 @@ stdenv.mkDerivation {
     ##
     ## Dynamic linker support
     ##
-    + ''
+    + optionalString (sharedLibraryLoader != null) ''
       if [[ -z ''${dynamicLinker+x} ]]; then
         echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
-        local dynamicLinker="${libc_lib}/lib/ld*.so.?"
+        local dynamicLinker="${sharedLibraryLoader}/lib/ld*.so.?"
       fi
     ''
 
@@ -246,9 +258,9 @@ stdenv.mkDerivation {
 
         ${if targetPlatform.isDarwin then ''
           printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
-        '' else ''
-          if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
-            echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
+        '' else lib.optionalString (sharedLibraryLoader != null) ''
+          if [ -e ${sharedLibraryLoader}/lib/32/ld-linux.so.2 ]; then
+            echo ${sharedLibraryLoader}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
           fi
           touch $out/nix-support/ld-set-dynamic-linker
         ''}
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index 54eb13d38ff3..cfa8204f0931 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -37,6 +37,10 @@
 
 let
 
+  inherit (lib)
+    optionals
+    ;
+
   mkDbExtraCommand = contents: let
     contentsList = if builtins.isList contents then contents else [ contents ];
   in ''
@@ -86,6 +90,8 @@ rec {
     , finalImageName ? imageName
       # This used to set a tag to the pulled image
     , finalImageTag ? "latest"
+      # This is used to disable TLS certificate verification, allowing access to http registries on (hopefully) trusted networks
+    , tlsVerify ? true
 
     , name ? fixName "docker-image-${finalImageName}-${finalImageTag}.tar"
     }:
@@ -105,7 +111,13 @@ rec {
       sourceURL = "docker://${imageName}@${imageDigest}";
       destNameTag = "${finalImageName}:${finalImageTag}";
     } ''
-      skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceURL" "docker-archive://$out:$destNameTag"
+      skopeo \
+        --src-tls-verify=${lib.boolToString tlsVerify} \
+        --insecure-policy \
+        --tmpdir=$TMPDIR \
+        --override-os ${os} \
+        --override-arch ${arch} \
+        copy "$sourceURL" "docker-archive://$out:$destNameTag"
     '';
 
   # We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash.
@@ -786,7 +798,11 @@ rec {
     fakeRootCommands ? "",
     # We pick 100 to ensure there is plenty of room for extension. I
     # believe the actual maximum is 128.
-    maxLayers ? 100
+    maxLayers ? 100,
+    # Whether to include store paths in the image. You generally want to leave
+    # this on, but tooling may disable this to insert the store paths more
+    # efficiently via other means, such as bind mounting the host store.
+    includeStorePaths ? true,
   }:
     assert
       (lib.assertMsg (maxLayers > 1)
@@ -834,7 +850,9 @@ rec {
         '';
       };
 
-      closureRoots = [ baseJson ] ++ contentsList;
+      closureRoots = optionals includeStorePaths /* normally true */ (
+        [ baseJson ] ++ contentsList
+      );
       overallClosure = writeText "closure" (lib.concatStringsSep " " closureRoots);
 
       # These derivations are only created as implementation details of docker-tools,
diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix
index 7dbee38feeb4..de90eab3ea1d 100644
--- a/pkgs/build-support/docker/examples.nix
+++ b/pkgs/build-support/docker/examples.nix
@@ -516,4 +516,29 @@ rec {
     bash
     layeredImageWithFakeRootCommands
   ];
+
+  helloOnRoot = pkgs.dockerTools.streamLayeredImage {
+    name = "hello";
+    tag = "latest";
+    contents = [
+      (pkgs.buildEnv {
+        name = "hello-root";
+        paths = [ pkgs.hello ];
+      })
+    ];
+    config.Cmd = [ "hello" ];
+  };
+
+  helloOnRootNoStore = pkgs.dockerTools.streamLayeredImage {
+    name = "hello";
+    tag = "latest";
+    contents = [
+      (pkgs.buildEnv {
+        name = "hello-root";
+        paths = [ pkgs.hello ];
+      })
+    ];
+    config.Cmd = [ "hello" ];
+    includeStorePaths = false;
+  };
 }
diff --git a/pkgs/build-support/fetchgitea/default.nix b/pkgs/build-support/fetchgitea/default.nix
new file mode 100644
index 000000000000..79804588cfe5
--- /dev/null
+++ b/pkgs/build-support/fetchgitea/default.nix
@@ -0,0 +1,7 @@
+# Gitea's URLs are compatible with GitHub
+
+{ lib, fetchFromGitHub }:
+
+{ domain, ... }@args:
+
+fetchFromGitHub ((removeAttrs args [ "domain" ]) // { githubBase = domain; })
diff --git a/pkgs/build-support/libredirect/libredirect.c b/pkgs/build-support/libredirect/libredirect.c
index c8d6956a6bfe..dfa2978e9f44 100644
--- a/pkgs/build-support/libredirect/libredirect.c
+++ b/pkgs/build-support/libredirect/libredirect.c
@@ -9,6 +9,7 @@
 #include <limits.h>
 #include <string.h>
 #include <spawn.h>
+#include <dirent.h>
 
 #define MAX_REDIRECTS 128
 
@@ -189,9 +190,85 @@ int posix_spawnp(pid_t * pid, const char * file,
     return posix_spawnp_real(pid, rewrite(file, buf), file_actions, attrp, argv, envp);
 }
 
-int execv(const char *path, char *const argv[])
+int execv(const char * path, char * const argv[])
 {
-    int (*execv_real) (const char *path, char *const argv[]) = dlsym(RTLD_NEXT, "execv");
+    int (*execv_real) (const char * path, char * const argv[]) = dlsym(RTLD_NEXT, "execv");
     char buf[PATH_MAX];
     return execv_real(rewrite(path, buf), argv);
 }
+
+int execvp(const char * path, char * const argv[])
+{
+    int (*_execvp) (const char *, char * const argv[]) = dlsym(RTLD_NEXT, "execvp");
+    char buf[PATH_MAX];
+    return _execvp(rewrite(path, buf), argv);
+}
+
+int execve(const char * path, char * const argv[], char * const envp[])
+{
+    int (*_execve) (const char *, char * const argv[], char * const envp[]) = dlsym(RTLD_NEXT, "execve");
+    char buf[PATH_MAX];
+    return _execve(rewrite(path, buf), argv, envp);
+}
+
+DIR * opendir(const char * path)
+{
+    char buf[PATH_MAX];
+    DIR * (*_opendir) (const char*) = dlsym(RTLD_NEXT, "opendir");
+
+    return _opendir(rewrite(path, buf));
+}
+
+#define SYSTEM_CMD_MAX 512
+
+char *replace_substring(char * source, char * buf, char * replace_string, char * start_ptr, char * suffix_ptr) {
+    char head[SYSTEM_CMD_MAX] = {0};
+    strncpy(head, source, start_ptr - source);
+
+    char tail[SYSTEM_CMD_MAX] = {0};
+    if(suffix_ptr < source + strlen(source)) {
+       strcpy(tail, suffix_ptr);
+    }
+
+    sprintf(buf, "%s%s%s", head, replace_string, tail);
+    return buf;
+}
+
+char *replace_string(char * buf, char * from, char * to) {
+    int num_matches = 0;
+    char * matches[SYSTEM_CMD_MAX];
+    int from_len = strlen(from);
+    for(int i=0; i<strlen(buf); i++){
+       char *cmp_start = buf + i;
+       if(strncmp(from, cmp_start, from_len) == 0){
+          matches[num_matches] = cmp_start;
+          num_matches++;
+       }
+    }
+    int len_diff = strlen(to) - strlen(from);
+    for(int n = 0; n < num_matches; n++) {
+       char replaced[SYSTEM_CMD_MAX];
+       replace_substring(buf, replaced, to, matches[n], matches[n]+from_len);
+       strcpy(buf, replaced);
+       for(int nn = n+1; nn < num_matches; nn++) {
+          matches[nn] += len_diff;
+       }
+    }
+    return buf;
+}
+
+void rewriteSystemCall(const char * command, char * buf) {
+    strcpy(buf, command);
+    for (int n = 0; n < nrRedirects; ++n) {
+       replace_string(buf, from[n], to[n]);
+    }
+}
+
+int system(const char *command)
+{
+    int (*_system) (const char*) = dlsym(RTLD_NEXT, "system");
+
+    char newCommand[SYSTEM_CMD_MAX];
+    rewriteSystemCall(command, newCommand);
+    return _system(newCommand);
+}
diff --git a/pkgs/build-support/libredirect/test.c b/pkgs/build-support/libredirect/test.c
index b57664db3c19..722d1303771c 100644
--- a/pkgs/build-support/libredirect/test.c
+++ b/pkgs/build-support/libredirect/test.c
@@ -2,6 +2,7 @@
 #include <fcntl.h>
 #include <spawn.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #include <sys/stat.h>
@@ -31,6 +32,10 @@ void test_execv(void) {
     assert(execv(TESTPATH, argv) == 0);
 }
 
+void test_system(void) {
+    assert(system(TESTPATH) == 0);
+}
+
 int main(void)
 {
     FILE *testfp;
@@ -50,6 +55,7 @@ int main(void)
     assert(stat(TESTPATH, &testsb) != -1);
 
     test_spawn();
+    test_system();
     test_execv();
 
     /* If all goes well, this is never reached because test_execv() replaces
diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix
index 940bd09425d2..be983af1c114 100644
--- a/pkgs/build-support/rust/default.nix
+++ b/pkgs/build-support/rust/default.nix
@@ -7,6 +7,7 @@
 , cargoInstallHook
 , cargoSetupHook
 , fetchCargoTarball
+, importCargoLock
 , runCommandNoCC
 , rustPlatform
 , callPackage
@@ -42,6 +43,7 @@
 , cargoDepsHook ? ""
 , buildType ? "release"
 , meta ? {}
+, cargoLock ? null
 , cargoVendorDir ? null
 , checkType ? buildType
 , depsExtraArgs ? {}
@@ -56,19 +58,22 @@
 , buildAndTestSubdir ? null
 , ... } @ args:
 
-assert cargoVendorDir == null -> !(cargoSha256 == "" && cargoHash == "");
+assert cargoVendorDir == null && cargoLock == null -> cargoSha256 == "" && cargoHash == ""
+  -> throw "cargoSha256, cargoHash, cargoVendorDir, or cargoLock must be set";
 assert buildType == "release" || buildType == "debug";
 
 let
 
-  cargoDeps = if cargoVendorDir == null
-    then fetchCargoTarball ({
-        inherit src srcs sourceRoot unpackPhase cargoUpdateHook;
-        name = cargoDepsName;
-        hash = cargoHash;
-        patches = cargoPatches;
-        sha256 = cargoSha256;
-      } // depsExtraArgs)
+  cargoDeps =
+    if cargoVendorDir == null
+    then if cargoLock != null then importCargoLock cargoLock
+    else fetchCargoTarball ({
+      inherit src srcs sourceRoot unpackPhase cargoUpdateHook;
+      name = cargoDepsName;
+      hash = cargoHash;
+      patches = cargoPatches;
+      sha256 = cargoSha256;
+    } // depsExtraArgs)
     else null;
 
   # If we have a cargoSha256 fixed-output derivation, validate it at build time
@@ -97,7 +102,7 @@ in
 # See https://os.phil-opp.com/testing/ for more information.
 assert useSysroot -> !(args.doCheck or true);
 
-stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // lib.optionalAttrs useSysroot {
+stdenv.mkDerivation ((removeAttrs args [ "depsExtraArgs" "cargoLock" ]) // lib.optionalAttrs useSysroot {
   RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or "");
 } // {
   inherit buildAndTestSubdir cargoDeps;
diff --git a/pkgs/build-support/rust/import-cargo-lock.nix b/pkgs/build-support/rust/import-cargo-lock.nix
new file mode 100644
index 000000000000..244572f79e80
--- /dev/null
+++ b/pkgs/build-support/rust/import-cargo-lock.nix
@@ -0,0 +1,167 @@
+{ fetchgit, fetchurl, lib, runCommand, cargo, jq }:
+
+{
+  # Cargo lock file
+  lockFile
+
+  # Hashes for git dependencies.
+, outputHashes ? {}
+}:
+
+let
+  # Parse a git source into different components.
+  parseGit = src:
+    let
+      parts = builtins.match ''git\+([^?]+)(\?rev=(.*))?#(.*)?'' src;
+      rev = builtins.elemAt parts 2;
+    in
+      if parts == null then null
+      else {
+        url = builtins.elemAt parts 0;
+        sha = builtins.elemAt parts 3;
+      } // lib.optionalAttrs (rev != null) { inherit rev; };
+
+  packages = (builtins.fromTOML (builtins.readFile lockFile)).package;
+
+  # There is no source attribute for the source package itself. But
+  # since we do not want to vendor the source package anyway, we can
+  # safely skip it.
+  depPackages = (builtins.filter (p: p ? "source") packages);
+
+  # Create dependent crates from packages.
+  #
+  # Force evaluation of the git SHA -> hash mapping, so that an error is
+  # thrown if there are stale hashes. We cannot rely on gitShaOutputHash
+  # being evaluated otherwise, since there could be no git dependencies.
+  depCrates = builtins.deepSeq (gitShaOutputHash) (builtins.map mkCrate depPackages);
+
+  # Map package name + version to git commit SHA for packages with a git source.
+  namesGitShas = builtins.listToAttrs (
+    builtins.map nameGitSha (builtins.filter (pkg: lib.hasPrefix "git+" pkg.source) depPackages)
+  );
+
+  nameGitSha = pkg: let gitParts = parseGit pkg.source; in {
+    name = "${pkg.name}-${pkg.version}";
+    value = gitParts.sha;
+  };
+
+  # Convert the attrset provided through the `outputHashes` argument to a
+  # a mapping from git commit SHA -> output hash.
+  #
+  # There may be multiple different packages with different names
+  # originating from the same git repository (typically a Cargo
+  # workspace). By using the git commit SHA as a universal identifier,
+  # the user does not have to specify the output hash for every package
+  # individually.
+  gitShaOutputHash = lib.mapAttrs' (nameVer: hash:
+    let
+      unusedHash = throw "A hash was specified for ${nameVer}, but there is no corresponding git dependency.";
+      rev = namesGitShas.${nameVer} or unusedHash; in {
+      name = rev;
+      value = hash;
+    }) outputHashes;
+
+  # We can't use the existing fetchCrate function, since it uses a
+  # recursive hash of the unpacked crate.
+  fetchCrate = pkg: fetchurl {
+    name = "crate-${pkg.name}-${pkg.version}.tar.gz";
+    url = "https://crates.io/api/v1/crates/${pkg.name}/${pkg.version}/download";
+    sha256 = pkg.checksum;
+  };
+
+  # Fetch and unpack a crate.
+  mkCrate = pkg:
+    let
+      gitParts = parseGit pkg.source;
+    in
+      if pkg.source == "registry+https://github.com/rust-lang/crates.io-index" then
+      let
+        crateTarball = fetchCrate pkg;
+      in runCommand "${pkg.name}-${pkg.version}" {} ''
+        mkdir $out
+        tar xf "${crateTarball}" -C $out --strip-components=1
+
+        # Cargo is happy with largely empty metadata.
+        printf '{"files":{},"package":"${pkg.checksum}"}' > "$out/.cargo-checksum.json"
+      ''
+      else if gitParts != null then
+      let
+        missingHash = throw ''
+          No hash was found while vendoring the git dependency ${pkg.name}-${pkg.version}. You can add
+          a hash through the `outputHashes` argument of `importCargoLock`:
+
+          outputHashes = {
+            "${pkg.name}-${pkg.version}" = "<hash>";
+          };
+
+          If you use `buildRustPackage`, you can add this attribute to the `cargoLock`
+          attribute set.
+        '';
+        sha256 = gitShaOutputHash.${gitParts.sha} or missingHash;
+        tree = fetchgit {
+          inherit sha256;
+          inherit (gitParts) url;
+          rev = gitParts.sha; # The commit SHA is always available.
+        };
+      in runCommand "${pkg.name}-${pkg.version}" {} ''
+        tree=${tree}
+        if grep --quiet '\[workspace\]' "$tree/Cargo.toml"; then
+          # If the target package is in a workspace, find the crate path
+          # using `cargo metadata`.
+          crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $tree/Cargo.toml | \
+            ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path')
+
+            if [[ ! -z $crateCargoTOML ]]; then
+              tree=$(dirname $crateCargoTOML)
+            else
+              >&2 echo "Cannot find path for crate '${pkg.name}-${pkg.version}' in the Cargo workspace in: $tree"
+              exit 1
+            fi
+        fi
+
+        cp -prvd "$tree/" $out
+        chmod u+w $out
+
+        # Cargo is happy with empty metadata.
+        printf '{"files":{},"package":null}' > "$out/.cargo-checksum.json"
+
+        # Set up configuration for the vendor directory.
+        cat > $out/.cargo-config <<EOF
+        [source."${gitParts.url}"]
+        git = "${gitParts.url}"
+        ${lib.optionalString (gitParts ? rev) "rev = \"${gitParts.rev}\""}
+        replace-with = "vendored-sources"
+        EOF
+      ''
+      else throw "Cannot handle crate source: ${pkg.source}";
+
+  vendorDir = runCommand "cargo-vendor-dir" {} ''
+    mkdir -p $out/.cargo
+
+    ln -s ${lockFile} $out/Cargo.lock
+
+    cat > $out/.cargo/config <<EOF
+    [source.crates-io]
+    replace-with = "vendored-sources"
+
+    [source.vendored-sources]
+    directory = "cargo-vendor-dir"
+    EOF
+
+    declare -A keysSeen
+
+    for crate in ${toString depCrates}; do
+      # Link the crate directory, removing the output path hash from the destination.
+      ln -s "$crate" $out/$(basename "$crate" | cut -c 34-)
+
+      if [ -e "$crate/.cargo-config" ]; then
+        key=$(sed 's/\[source\."\(.*\)"\]/\1/; t; d' < "$crate/.cargo-config")
+        if [[ -z ''${keysSeen[$key]} ]]; then
+          keysSeen[$key]=1
+          cat "$crate/.cargo-config" >> $out/.cargo/config
+        fi
+      fi
+    done
+  '';
+in
+  vendorDir
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.lock b/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.lock
new file mode 100644
index 000000000000..fd1b5e42ad30
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.lock
@@ -0,0 +1,83 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "basic"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.toml b/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.toml
new file mode 100644
index 000000000000..f555bb0de62e
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/basic/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "basic"
+version = "0.1.0"
+authors = ["Daniël de Kok <me@danieldk.eu>"]
+edition = "2018"
+
+[dependencies]
+rand = "0.8"
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/basic/default.nix b/pkgs/build-support/rust/test/import-cargo-lock/basic/default.nix
new file mode 100644
index 000000000000..d595b58109ad
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/basic/default.nix
@@ -0,0 +1,18 @@
+{ rustPlatform }:
+
+rustPlatform.buildRustPackage {
+  pname = "basic";
+  version = "0.1.0";
+
+  src = ./.;
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+  };
+
+  doInstallCheck = true;
+
+  installCheckPhase = ''
+    $out/bin/basic
+  '';
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/basic/src/main.rs b/pkgs/build-support/rust/test/import-cargo-lock/basic/src/main.rs
new file mode 100644
index 000000000000..50b4ed799e43
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/basic/src/main.rs
@@ -0,0 +1,9 @@
+use rand::Rng;
+
+fn main() {
+    let mut rng = rand::thread_rng();
+
+    // Always draw zero :).
+    let roll: u8 = rng.gen_range(0..1);
+    assert_eq!(roll, 0);
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/default.nix b/pkgs/build-support/rust/test/import-cargo-lock/default.nix
new file mode 100644
index 000000000000..2dd525a8ac3f
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/default.nix
@@ -0,0 +1,8 @@
+{ callPackage }:
+
+{
+  basic = callPackage ./basic { };
+  gitDependency = callPackage ./git-dependency { };
+  gitDependencyNoRev = callPackage ./git-dependency-no-rev { };
+  maturin = callPackage ./maturin { };
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.lock b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.lock
new file mode 100644
index 000000000000..54b9c7c5739d
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.lock
@@ -0,0 +1,79 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "git-dependency-no-rev"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "git+https://github.com/rust-random/rand.git#f0e01ee0a7257753cc51b291f62666f4765923ef"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "git+https://github.com/rust-random/rand.git#f0e01ee0a7257753cc51b291f62666f4765923ef"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "git+https://github.com/rust-random/rand.git#f0e01ee0a7257753cc51b291f62666f4765923ef"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "git+https://github.com/rust-random/rand.git#f0e01ee0a7257753cc51b291f62666f4765923ef"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.toml b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.toml
new file mode 100644
index 000000000000..770dfb86f523
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "git-dependency-no-rev"
+version = "0.1.0"
+authors = ["Daniël de Kok <me@danieldk.eu>"]
+edition = "2018"
+
+[dependencies]
+rand = { git = "https://github.com/rust-random/rand.git" }
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/default.nix b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/default.nix
new file mode 100644
index 000000000000..fc36edc40772
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/default.nix
@@ -0,0 +1,21 @@
+{ rustPlatform }:
+
+rustPlatform.buildRustPackage {
+  pname = "git-dependency-no-rev";
+  version = "0.1.0";
+
+  src = ./.;
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+    outputHashes = {
+      "rand-0.8.3" = "0ya2hia3cn31qa8894s3av2s8j5bjwb6yq92k0jsnlx7jid0jwqa";
+    };
+  };
+
+  doInstallCheck = true;
+
+  installCheckPhase = ''
+    $out/bin/git-dependency-no-rev
+  '';
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/src/main.rs b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/src/main.rs
new file mode 100644
index 000000000000..50b4ed799e43
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency-no-rev/src/main.rs
@@ -0,0 +1,9 @@
+use rand::Rng;
+
+fn main() {
+    let mut rng = rand::thread_rng();
+
+    // Always draw zero :).
+    let roll: u8 = rng.gen_range(0..1);
+    assert_eq!(roll, 0);
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.lock b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.lock
new file mode 100644
index 000000000000..50600ef4caa5
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.lock
@@ -0,0 +1,79 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "git-dependency"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "git+https://github.com/rust-random/rand.git?rev=0.8.3#6ecbe2626b2cc6110a25c97b1702b347574febc7"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "git+https://github.com/rust-random/rand.git?rev=0.8.3#6ecbe2626b2cc6110a25c97b1702b347574febc7"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.1"
+source = "git+https://github.com/rust-random/rand.git?rev=0.8.3#6ecbe2626b2cc6110a25c97b1702b347574febc7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "git+https://github.com/rust-random/rand.git?rev=0.8.3#6ecbe2626b2cc6110a25c97b1702b347574febc7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.toml b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.toml
new file mode 100644
index 000000000000..11ee8b1763e6
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "git-dependency"
+version = "0.1.0"
+authors = ["Daniël de Kok <me@danieldk.eu>"]
+edition = "2018"
+
+[dependencies]
+rand = { git = "https://github.com/rust-random/rand.git", rev = "0.8.3" }
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/default.nix b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/default.nix
new file mode 100644
index 000000000000..17276c5f5c3c
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/default.nix
@@ -0,0 +1,21 @@
+{ rustPlatform }:
+
+rustPlatform.buildRustPackage {
+  pname = "git-dependency";
+  version = "0.1.0";
+
+  src = ./.;
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+    outputHashes = {
+      "rand-0.8.3" = "0l3p174bpwia61vcvxz5mw65a13ri3wy94z04xrnyy5lzciykz4f";
+    };
+  };
+
+  doInstallCheck = true;
+
+  installCheckPhase = ''
+    $out/bin/git-dependency
+  '';
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/src/main.rs b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/src/main.rs
new file mode 100644
index 000000000000..50b4ed799e43
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/git-dependency/src/main.rs
@@ -0,0 +1,9 @@
+use rand::Rng;
+
+fn main() {
+    let mut rng = rand::thread_rng();
+
+    // Always draw zero :).
+    let roll: u8 = rng.gen_range(0..1);
+    assert_eq!(roll, 0);
+}
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/maturin/Cargo.lock b/pkgs/build-support/rust/test/import-cargo-lock/maturin/Cargo.lock
new file mode 100644
index 000000000000..5e698d4ff735
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/maturin/Cargo.lock
@@ -0,0 +1,682 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ahash"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
+
+[[package]]
+name = "assert_approx_eq"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c07dab4369547dbe5114677b33fbbf724971019f3818172d59a97a61c774ffd"
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "byteorder"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "const_fn"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
+dependencies = [
+ "cfg-if",
+ "const_fn",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "ctor"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "ghost"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "hashbrown"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "indoc"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
+dependencies = [
+ "indoc-impl",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "indoc-impl"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unindent",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "inventory"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f"
+dependencies = [
+ "ctor",
+ "ghost",
+ "inventory-impl",
+]
+
+[[package]]
+name = "inventory-impl"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+
+[[package]]
+name = "lock_api"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "paste"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
+dependencies = [
+ "paste-impl",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "paste-impl"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
+dependencies = [
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "proptest"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12e6c80c1139113c28ee4670dc50cc42915228b51f56a9e407f0ec60f966646f"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "lazy_static",
+ "num-traits",
+ "quick-error",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+]
+
+[[package]]
+name = "pyo3"
+version = "0.13.2"
+dependencies = [
+ "assert_approx_eq",
+ "cfg-if",
+ "ctor",
+ "hashbrown",
+ "indoc",
+ "inventory",
+ "libc",
+ "num-bigint",
+ "num-complex",
+ "parking_lot",
+ "paste",
+ "proptest",
+ "pyo3",
+ "pyo3-macros",
+ "rustversion",
+ "serde",
+ "serde_json",
+ "trybuild",
+ "unindent",
+]
+
+[[package]]
+name = "pyo3-macros"
+version = "0.13.2"
+dependencies = [
+ "pyo3-macros-backend",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pyo3-macros-backend"
+version = "0.13.2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
+
+[[package]]
+name = "rustapi-module"
+version = "0.1.0"
+dependencies = [
+ "pyo3",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.123"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.123"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
+
+[[package]]
+name = "syn"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "trybuild"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b"
+dependencies = [
+ "glob",
+ "lazy_static",
+ "serde",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "unindent"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "word-count"
+version = "0.1.0"
+dependencies = [
+ "pyo3",
+ "rayon",
+]
diff --git a/pkgs/build-support/rust/test/import-cargo-lock/maturin/default.nix b/pkgs/build-support/rust/test/import-cargo-lock/maturin/default.nix
new file mode 100644
index 000000000000..af0de596b387
--- /dev/null
+++ b/pkgs/build-support/rust/test/import-cargo-lock/maturin/default.nix
@@ -0,0 +1,43 @@
+{ lib
+, fetchFromGitHub
+, python3
+, rustPlatform
+}:
+
+python3.pkgs.buildPythonPackage rec {
+  pname = "word-count";
+  version = "0.13.2";
+
+  format = "pyproject";
+
+  src = fetchFromGitHub {
+    owner = "PyO3";
+    repo = "pyo3";
+    rev = "v${version}";
+    hash = "sha256-NOMrrfo8WjlPhtGxWUOPJS/UDDdbLQRCXR++Zd6JmIA=";
+  };
+
+  cargoDeps = rustPlatform.importCargoLock {
+    lockFile = ./Cargo.lock;
+  };
+
+  postPatch = ''
+    cp ${./Cargo.lock} Cargo.lock
+  '';
+
+  buildAndTestSubdir = "examples/word-count";
+
+  nativeBuildInputs = with rustPlatform; [
+    cargoSetupHook
+    maturinBuildHook
+  ];
+
+  pythonImportsCheck = [ "word_count" ];
+
+  meta = with lib; {
+    description = "PyO3 word count example";
+    homepage = "https://github.com/PyO3/pyo3";
+    license = licenses.asl20;
+    maintainers = [ maintainers.danieldk ];
+  };
+}
diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index f6be1b299f61..cfc19c03cfdd 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -822,45 +822,6 @@ rec {
   /* The set of supported Dpkg-based distributions. */
 
   debDistros = {
-
-    # Interestingly, the SHA-256 hashes provided by Ubuntu in
-    # http://nl.archive.ubuntu.com/ubuntu/dists/{gutsy,hardy}/Release are
-    # wrong, but the SHA-1 and MD5 hashes are correct.  Intrepid is fine.
-
-    ubuntu1204i386 = {
-      name = "ubuntu-12.04-precise-i386";
-      fullName = "Ubuntu 12.04 Precise (i386)";
-      packagesLists =
-        [ (fetchurl {
-            url = "mirror://ubuntu/dists/precise/main/binary-i386/Packages.bz2";
-            sha256 = "18ns9h4qhvjfcip9z55grzi371racxavgqkp6b5kfkdq2wwwax2d";
-          })
-          (fetchurl {
-            url = "mirror://ubuntu/dists/precise/universe/binary-i386/Packages.bz2";
-            sha256 = "085lkzbnzkc74kfdmwdc32sfqyfz8dr0rbiifk8kx9jih3xjw2jk";
-          })
-        ];
-      urlPrefix = "mirror://ubuntu";
-      packages = commonDebPackages ++ [ "diffutils" ];
-    };
-
-    ubuntu1204x86_64 = {
-      name = "ubuntu-12.04-precise-amd64";
-      fullName = "Ubuntu 12.04 Precise (amd64)";
-      packagesLists =
-        [ (fetchurl {
-            url = "mirror://ubuntu/dists/precise/main/binary-amd64/Packages.bz2";
-            sha256 = "1aabpn0hdih6cbabyn87yvhccqj44q9k03mqmjsb920iqlckl3fc";
-          })
-          (fetchurl {
-            url = "mirror://ubuntu/dists/precise/universe/binary-amd64/Packages.bz2";
-            sha256 = "0x4hz5aplximgb7gnpvrhkw8m7a40s80rkm5b8hil0afblwlg4vr";
-          })
-        ];
-      urlPrefix = "mirror://ubuntu";
-      packages = commonDebPackages ++ [ "diffutils" ];
-    };
-
     ubuntu1404i386 = {
       name = "ubuntu-14.04-trusty-i386";
       fullName = "Ubuntu 14.04 Trusty (i386)";
@@ -929,119 +890,117 @@ rec {
       packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
     };
 
-    ubuntu1710i386 = {
-      name = "ubuntu-17.10-artful-i386";
-      fullName = "Ubuntu 17.10 Artful (i386)";
+    ubuntu1804i386 = {
+      name = "ubuntu-18.04-bionic-i386";
+      fullName = "Ubuntu 18.04 Bionic (i386)";
       packagesLists =
         [ (fetchurl {
-            url = "mirror://ubuntu/dists/artful/main/binary-i386/Packages.xz";
-            sha256 = "18yrj4kqdzm39q0527m97h5ing58hkm9yq9iyj636zh2rclym3c8";
+            url = "mirror://ubuntu/dists/bionic/main/binary-i386/Packages.xz";
+            sha256 = "0f0v4131kwf7m7f8j3288rlqdxk1k3vqy74b7fcfd6jz9j8d840i";
           })
           (fetchurl {
-            url = "mirror://ubuntu/dists/artful/universe/binary-i386/Packages.xz";
-            sha256 = "1v0njw2w80xfmxi7by76cs8hyxlla5h3gqajlpdw5srjgx2qrm2g";
+            url = "mirror://ubuntu/dists/bionic/universe/binary-i386/Packages.xz";
+            sha256 = "1v75c0dqr0wp0dqd4hnci92qqs4hll8frqdbpswadgxm5chn91bw";
           })
         ];
       urlPrefix = "mirror://ubuntu";
       packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
     };
 
-    ubuntu1710x86_64 = {
-      name = "ubuntu-17.10-artful-amd64";
-      fullName = "Ubuntu 17.10 Artful (amd64)";
+    ubuntu1804x86_64 = {
+      name = "ubuntu-18.04-bionic-amd64";
+      fullName = "Ubuntu 18.04 Bionic (amd64)";
       packagesLists =
         [ (fetchurl {
-            url = "mirror://ubuntu/dists/artful/main/binary-amd64/Packages.xz";
-            sha256 = "104g57j1l3vi8wb5f7rgjvjhf82ccs0vwhc59jfc4ynd51z7fqjk";
+            url = "mirror://ubuntu/dists/bionic/main/binary-amd64/Packages.xz";
+            sha256 = "1ls81bjyvmfz6i919kszl7xks1ibrh1xqhsk6698ackndkm0wp39";
           })
           (fetchurl {
-            url = "mirror://ubuntu/dists/artful/universe/binary-amd64/Packages.xz";
-            sha256 = "1qzs95wfy9inaskfx9cf1l5yd3aaqwzy72zzi9xyvkxi75k5gcn4";
+            url = "mirror://ubuntu/dists/bionic/universe/binary-amd64/Packages.xz";
+            sha256 = "1832nqpn4ap95b3sj870xqayrza9in4kih9jkmjax27pq6x15v1r";
           })
         ];
       urlPrefix = "mirror://ubuntu";
       packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
     };
 
-    ubuntu1804i386 = {
-      name = "ubuntu-18.04-bionic-i386";
-      fullName = "Ubuntu 18.04 Bionic (i386)";
+    ubuntu2004i386 = {
+      name = "ubuntu-20.04-focal-i386";
+      fullName = "Ubuntu 20.04 Focal (i386)";
       packagesLists =
         [ (fetchurl {
-            url = "mirror://ubuntu/dists/bionic/main/binary-i386/Packages.xz";
-            sha256 = "0f0v4131kwf7m7f8j3288rlqdxk1k3vqy74b7fcfd6jz9j8d840i";
+            url = "mirror://ubuntu/dists/focal/main/binary-i386/Packages.xz";
+            sha256 = "sha256-7RAYURoN3RKYQAHpwBS9TIV6vCmpURpphyMJQmV4wLc=";
           })
           (fetchurl {
-            url = "mirror://ubuntu/dists/bionic/universe/binary-i386/Packages.xz";
-            sha256 = "1v75c0dqr0wp0dqd4hnci92qqs4hll8frqdbpswadgxm5chn91bw";
+            url = "mirror://ubuntu/dists/focal/universe/binary-i386/Packages.xz";
+            sha256 = "sha256-oA551xVE80volUPgkMyvzpQ1d+GhuZd4DAe7dXZnULM=";
           })
         ];
       urlPrefix = "mirror://ubuntu";
       packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
     };
 
-    ubuntu1804x86_64 = {
-      name = "ubuntu-18.04-bionic-amd64";
-      fullName = "Ubuntu 18.04 Bionic (amd64)";
+    ubuntu2004x86_64 = {
+      name = "ubuntu-20.04-focal-amd64";
+      fullName = "Ubuntu 20.04 Focal (amd64)";
       packagesLists =
         [ (fetchurl {
-            url = "mirror://ubuntu/dists/bionic/main/binary-amd64/Packages.xz";
-            sha256 = "1ls81bjyvmfz6i919kszl7xks1ibrh1xqhsk6698ackndkm0wp39";
+            url = "mirror://ubuntu/dists/focal/main/binary-amd64/Packages.xz";
+            sha256 = "sha256-d1eSH/j+7Zw5NKDJk21EG6SiOL7j6myMHfXLzUP8mGE=";
           })
           (fetchurl {
-            url = "mirror://ubuntu/dists/bionic/universe/binary-amd64/Packages.xz";
-            sha256 = "1832nqpn4ap95b3sj870xqayrza9in4kih9jkmjax27pq6x15v1r";
+            url = "mirror://ubuntu/dists/focal/universe/binary-amd64/Packages.xz";
+            sha256 = "sha256-RqdG2seJvZU3rKVNsWgLnf9RwkgVMRE1A4IZnX2WudE=";
           })
         ];
       urlPrefix = "mirror://ubuntu";
       packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
     };
 
-    debian8i386 = {
-      name = "debian-8.11-jessie-i386";
-      fullName = "Debian 8.11 Jessie (i386)";
+    debian9i386 = {
+      name = "debian-9.13-stretch-i386";
+      fullName = "Debian 9.13 Stretch (i386)";
       packagesList = fetchurl {
-        url = "mirror://debian/dists/jessie/main/binary-i386/Packages.xz";
-        sha256 = "0adblarhx50yga900il6m25ng0csa81i3wid1dxxmydbdmri7v7d";
+        url = "https://snapshot.debian.org/archive/debian/20210526T143040Z/dists/stretch/main/binary-i386/Packages.xz";
+        sha256 = "sha256-fFRumd20wuVaYxzw0VPkAw5mQo8kIg+eXII15VSz9wA=";
       };
       urlPrefix = "mirror://debian";
       packages = commonDebianPackages;
     };
 
-    debian8x86_64 = {
-      name = "debian-8.11-jessie-amd64";
-      fullName = "Debian 8.11 Jessie (amd64)";
+    debian9x86_64 = {
+      name = "debian-9.13-stretch-amd64";
+      fullName = "Debian 9.13 Stretch (amd64)";
       packagesList = fetchurl {
-        url = "mirror://debian/dists/jessie/main/binary-amd64/Packages.xz";
-        sha256 = "09y1mv4kqllhxpk1ibjsyl5jig5bp0qxw6pp4sn56rglrpygmn5x";
+        url = "https://snapshot.debian.org/archive/debian/20210526T143040Z/dists/stretch/main/binary-amd64/Packages.xz";
+        sha256 = "sha256-1p4DEVpTGlBE3PtbQ90kYw4QNHkW0F4rna/Xz+ncMhw=";
       };
       urlPrefix = "mirror://debian";
       packages = commonDebianPackages;
     };
 
-    debian9i386 = {
-      name = "debian-9.8-stretch-i386";
-      fullName = "Debian 9.8 Stretch (i386)";
+    debian10i386 = {
+      name = "debian-10.9-buster-i386";
+      fullName = "Debian 10.9 Buster (i386)";
       packagesList = fetchurl {
-        url = "http://snapshot.debian.org/archive/debian/20200301T030401Z/dists/stretch/main/binary-i386/Packages.xz";
-        sha256 = "1jglr1d1jys3xddp8f7w9j05db39fah8xy4gfkpqbd1b5d2caslz";
+        url = "https://snapshot.debian.org/archive/debian/20210526T143040Z/dists/buster/main/binary-i386/Packages.xz";
+        sha256 = "sha256-zlkbKV+IGBCyWKD4v4LFM/EUA4TYS9fkLBPuF6MgUDo=";
       };
       urlPrefix = "mirror://debian";
       packages = commonDebianPackages;
     };
 
-    debian9x86_64 = {
-      name = "debian-9.8-stretch-amd64";
-      fullName = "Debian 9.8 Stretch (amd64)";
+    debian10x86_64 = {
+      name = "debian-10.9-buster-amd64";
+      fullName = "Debian 10.9 Buster (amd64)";
       packagesList = fetchurl {
-        url = "http://snapshot.debian.org/archive/debian/20190503T090946Z/dists/stretch/main/binary-amd64/Packages.xz";
-        sha256 = "01q00nl47p12n7wx0xclx59wf3zlkzrgj3zxpshyvb91xdnw5sh6";
+        url = "https://snapshot.debian.org/archive/debian/20210526T143040Z/dists/buster/main/binary-amd64/Packages.xz";
+        sha256 = "sha256-k13toY1b3CX7GBPQ7Jm24OMqCEsgPlGK8M99x57o69o=";
       };
       urlPrefix = "mirror://debian";
       packages = commonDebianPackages;
     };
-
-
   };
 
 
@@ -1168,7 +1127,7 @@ rec {
     "passwd"
   ];
 
-  commonDebianPackages = commonDebPackages ++ [ "sysvinit" "diff" "mktemp" ];
+  commonDebianPackages = commonDebPackages ++ [ "sysvinit" "diff" ];
 
 
   /* A set of functions that build the Linux distributions specified