anchor.diff:          then abort
             "The values in sources.json should not have an 'outPath' attribute"
           else
  -          spec // { outPath = fetch config.pkgs name spec; }
  +          spec // { outPath = replace name (fetch config.pkgs name spec); }
       ) config.sources;
   
     # The "config" used by the fetchers
     mkConfig =
  -    { sourcesFile ? ./sources.json
  -    , sources ? builtins.fromJSON (builtins.readFile sourcesFile)
  -    , pkgs ? mkPkgs sources
  +    { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
  +    , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
  +    , system ? builtins.currentSystem
  +    , pkgs ? mkPkgs sources system
       }: rec {
         # The sources, i.e. the attribute set of spec name to spec
         inherit sources;
  
positive.code:   # The fetchers. fetch_<type> fetches specs of type <type>.
    #
  
    fetch_file = pkgs: spec:
      if spec.builtin or true then
        builtins_fetchurl { inherit (spec) url sha256; }
      else
        pkgs.fetchurl { inherit (spec) url sha256; };
  
    fetch_tarball = pkgs: spec:
      if spec.builtin or true then
        builtins_fetchTarball { inherit (spec) url sha256; }
      else
        pkgs.fetchzip { inherit (spec) url sha256; };
  
    fetch_git = spec:
      builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
  
    fetch_builtin-tarball = spec:
      builtins.trace
        ''
          WARNING:
            The niv type "builtin-tarball" will soon be deprecated. You should
            instead use `builtin = true`.
  
            $ niv modify <package> -a type=tarball -a builtin=true
        ''
        builtins_fetchTarball { inherit (spec) url sha256; };
  
    fetch_builtin-url = spec:
      builtins.trace
        ''
          WARNING:
            The niv type "builtin-url" will soon be deprecated. You should
            instead use `builtin = true`.
  
            $ niv modify <package> -a type=file -a builtin=true
        ''
        (builtins_fetchurl { inherit (spec) url sha256; });
  
    #
    # Various helpers
    #
  
    # The set of packages used when specs are fetched using non-builtins.
    mkPkgs = sources:
      let
        sourcesNixpkgs =
          import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
        hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
        hasThisAsNixpkgsPath = <nixpkgs> == ./.;
      in
  
negative.code: 
      if ! builtins.hasAttr "type" spec then
        abort "ERROR: niv spec ${name} does not have a 'type' attribute"
      else if spec.type == "file" then fetch_file pkgs name spec
      else if spec.type == "tarball" then fetch_tarball pkgs name spec
      else if spec.type == "git" then fetch_git name spec
      else if spec.type == "local" then fetch_local spec
      else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
      else if spec.type == "builtin-url" then fetch_builtin-url name
      else
        abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
  
    # If the environment variable NIV_OVERRIDE_${name} is set, then use
    # the path directly as opposed to the fetched source.
    replace = name: drv:
      let
        saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
        ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
      in
        if ersatz == "" then drv else ersatz;
  
    # Ports of functions for older nix versions
  
  