{ 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 ; }