tvl-depot/users/Profpatsch/exactSource.nix

91 lines
2.7 KiB
Nix
Raw Permalink Normal View History

{ ... }:
# SPDX-License-Identifier: MIT
# Created by Graham Christensen
# version from https://github.com/grahamc/mayday/blob/c48f7583e622fe2e695a2a929de34679e5818816/exact-source.nix
let
# Require that every path specified does exist.
#
# By default, Nix won't complain if you refer to a missing file
# if you don't actually use it:
#
# nix-repl> ./bogus
# /home/grahamc/playground/bogus
#
# nix-repl> toString ./bogus
# "/home/grahamc/playground/bogus"
#
# so in order for this interface to be *exact*, we must
# specifically require every provided path exists:
#
# nix-repl> "${./bogus}"
# error: getting attributes of path
# '/home/grahamc/playground/bogus': No such file or
# directory
requireAllPathsExist = paths:
let
validation = builtins.map (path: "${path}") paths;
in
builtins.deepSeq validation paths;
# Break down a given path in to a list of all of the path and
# its parent directories.
#
# `builtins.path` / `builtins.filterSource` will ask about
# a containing directory, and we must say YES otherwise it will
# not include anything below it.
#
# Concretely, convert: "/foo/baz/tux" in to:
# [ "/foo/baz/tux" "/foo/baz" "/foo" ]
recursivelyPopDir = path:
if path == "/" then [ ]
else [ path ] ++ (recursivelyPopDir (builtins.dirOf path));
# Given a list of of strings, dedup the list and return a
# list of all unique strings.
#
# Note: only works on strings ;):
#
# First convert [ "foo" "foo" "bar" ] in to:
# [
# { name = "foo"; value = ""; }
# { name = "foo"; value = ""; }
# { name = "bar"; value = ""; }
# ]
# then convert that to { "foo" = ""; "bar" = ""; }
# then get the attribute names, "foo" and "bar".
dedup = strings:
let
name_value_pairs = builtins.map
(string: { name = string; value = ""; })
strings;
attrset_of_strings = builtins.listToAttrs name_value_pairs;
in
builtins.attrNames attrset_of_strings;
exactSource = source_root: paths:
let
all_possible_paths =
let
# Convert all the paths in to relative paths on disk.
# ie: stringPaths will contain [ "/home/grahamc/playground/..." ];
# instead of /nix/store paths.
string_paths = builtins.map toString
(requireAllPathsExist paths);
all_paths_with_duplicates = builtins.concatMap
recursivelyPopDir
string_paths;
in
dedup all_paths_with_duplicates;
pathIsSpecified = path:
builtins.elem path all_possible_paths;
in
builtins.path {
path = source_root;
filter = (path: _type: pathIsSpecified path);
};
in
exactSource