core/pkgs/build-support/dart/pub2nix/pubspec-lock.nix
2024-05-13 11:34:52 -04:00

120 lines
4.2 KiB
Nix

{ lib
, callPackage
, fetchurl
, fetchgit
, runCommand
}:
{
# The source directory of the package.
src
# The package subdirectory within src.
# Useful if the package references sibling packages with relative paths.
, packageRoot ? "."
# The pubspec.lock file, in attribute set form.
, pubspecLock
# Hashes for Git dependencies.
# Pub does not record these itself, so they must be manually provided.
, gitHashes ? { }
# Functions to generate SDK package sources.
# The function names should match the SDK names, and the package name is given as an argument.
, sdkSourceBuilders ? { }
# Functions that create custom package source derivations.
#
# The function names should match the package names, and the package version,
# source, and source files are given in an attribute set argument.
#
# The passthru of the source derivation should be propagated.
, customSourceBuilders ? { }
}:
let
dependencyVersions = builtins.mapAttrs (name: details: details.version) pubspecLock.packages;
dependencyTypes = {
"direct main" = "main";
"direct dev" = "dev";
"direct overridden" = "overridden";
"transitive" = "transitive";
};
dependencies = lib.foldlAttrs
(dependencies: name: details: dependencies // { ${dependencyTypes.${details.dependency}} = dependencies.${dependencyTypes.${details.dependency}} ++ [ name ]; })
(lib.genAttrs (builtins.attrValues dependencyTypes) (dependencyType: [ ]))
pubspecLock.packages;
# fetchTarball fails with "tarball contains an unexpected number of top-level files". This is a workaround.
# https://discourse.nixos.org/t/fetchtarball-with-multiple-top-level-directories-fails/20556
mkHostedDependencySource = name: details:
let
archive = fetchurl {
name = "pub-${name}-${details.version}.tar.gz";
url = "${details.description.url}/packages/${details.description.name}/versions/${details.version}.tar.gz";
sha256 = details.description.sha256;
};
in
runCommand "pub-${name}-${details.version}" { passthru.packageRoot = "."; } ''
mkdir -p "$out"
tar xf '${archive}' -C "$out"
'';
mkGitDependencySource = name: details: (fetchgit {
name = "pub-${name}-${details.version}";
url = details.description.url;
rev = details.description.resolved-ref;
hash = gitHashes.${name} or (throw "A Git hash is required for ${name}! Set to an empty string to obtain it.");
}).overrideAttrs ({ passthru ? { }, ... }: {
passthru = passthru // {
packageRoot = details.description.path;
};
});
mkPathDependencySource = name: details:
assert lib.assertMsg details.description.relative "Only relative paths are supported - ${name} has an absolue path!";
(if lib.isDerivation src then src else (runCommand "pub-${name}-${details.version}" { } ''cp -r '${src}' "$out"'')).overrideAttrs ({ passthru ? { }, ... }: {
passthru = passthru // {
packageRoot = "${packageRoot}/${details.description.path}";
};
});
mkSdkDependencySource = name: details:
(sdkSourceBuilders.${details.description} or (throw "No SDK source builder has been given for ${details.description}!")) name;
addDependencySourceUtils = dependencySource: details: dependencySource.overrideAttrs ({ passthru, ... }: {
passthru = passthru // {
inherit (details) version;
};
});
sourceBuilders = callPackage ../../../development/compilers/dart/package-source-builders { } // customSourceBuilders;
dependencySources = lib.filterAttrs (name: src: src != null) (builtins.mapAttrs
(name: details:
(sourceBuilders.${name} or ({ src, ... }: src)) {
inherit (details) version source;
src = ((addDependencySourceUtils (({
"hosted" = mkHostedDependencySource;
"git" = mkGitDependencySource;
"path" = mkPathDependencySource;
"sdk" = mkSdkDependencySource;
}.${details.source} name) details)) details);
})
pubspecLock.packages);
in
{
inherit
# An attribute set of dependency categories to package name lists.
dependencies
# An attribute set of package names to their versions.
dependencyVersions
# An attribute set of package names to their sources.
dependencySources;
}