Merge pull request #64 from hercules-ci/fix-dir-with-ignored-contents
Fix dir with ignored contents
This commit is contained in:
commit
9e21c80adf
8 changed files with 112 additions and 15 deletions
|
|
@ -2,6 +2,7 @@
|
|||
let
|
||||
parse-ini = import ./parse-git-config.nix { inherit lib; };
|
||||
parse-gitignore = import ./rules.nix { inherit lib; };
|
||||
path = import ./lib/path.nix { inherit lib; };
|
||||
in
|
||||
rec {
|
||||
inherit (builtins) dirOf baseNameOf abort split hasAttr readFile readDir pathExists;
|
||||
|
|
@ -27,14 +28,20 @@ rec {
|
|||
lib.optional (extraRules != null) { contextDir = basePath; rules = extraRules; };
|
||||
patternsBelowP = findPatternsTree extraRules2 basePath;
|
||||
basePathStr = toString basePath;
|
||||
in
|
||||
path: type: let
|
||||
localDirPath = removePrefix basePathStr (toString (dirOf path));
|
||||
localDirPathElements = splitString "/" localDirPath;
|
||||
patternResult = parse-gitignore.runFilterPattern (getPatterns patternsBelowP localDirPathElements)."/patterns" path type;
|
||||
nonempty = any (nodeName: gitignoreFilter (basePath + "/${nodeName}") != false)
|
||||
(attrNames (readDir path));
|
||||
in patternResult && (type == "directory" -> nonempty);
|
||||
rawFilter =
|
||||
path: type: let
|
||||
localDirPath = removePrefix basePathStr (toString (dirOf path));
|
||||
localDirPathElements = splitString "/" localDirPath;
|
||||
patternResult = parse-gitignore.runFilterPattern (getPatterns patternsBelowP localDirPathElements)."/patterns" path type;
|
||||
contents = readDir path;
|
||||
nonempty = localDirPathElements == [] || any (nodeName: memoFilter (path + "/${nodeName}") != false)
|
||||
(attrNames contents);
|
||||
in patternResult && (type == "directory" -> nonempty);
|
||||
memoFilter =
|
||||
path.memoize rawFilter
|
||||
(p: throw "Could not find path ${toString p} in memo table. Did path or filtering semantics change?")
|
||||
basePath;
|
||||
in path: type: memoFilter path;
|
||||
|
||||
getPatterns =
|
||||
patternTree: pathElems:
|
||||
|
|
|
|||
6
flake.lock
generated
6
flake.lock
generated
|
|
@ -2,11 +2,11 @@
|
|||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1632846328,
|
||||
"narHash": "sha256-sFi6YtlGK30TBB9o6CW7LG9mYHkgtKeWbSLAjjrNTX0=",
|
||||
"lastModified": 1666603677,
|
||||
"narHash": "sha256-apAEIj+z1iwMaMJ4tB21r/VTetfGDLDzuhXRHJknIAU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2b71ddd869ad592510553d09fe89c9709fa26b2b",
|
||||
"rev": "074da18a72269cc5a6cf444dce42daea5649b2fe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
11
flake.nix
11
flake.nix
|
|
@ -1,13 +1,16 @@
|
|||
{
|
||||
description = "Nix functions for filtering local git sources";
|
||||
description = "Nix functions for filtering local sources";
|
||||
|
||||
outputs = { self, nixpkgs }: {
|
||||
lib = import ./default.nix {
|
||||
inherit (nixpkgs) lib;
|
||||
};
|
||||
|
||||
overlay = final: prev: import ./default.nix {
|
||||
inherit (prev) lib;
|
||||
};
|
||||
overlay = final: prev:
|
||||
import ./default.nix {
|
||||
inherit (prev) lib;
|
||||
};
|
||||
|
||||
checks.x86_64-linux = import ./tests { pkgs = nixpkgs.legacyPackages.x86_64-linux; };
|
||||
};
|
||||
}
|
||||
|
|
|
|||
82
lib/path.nix
Normal file
82
lib/path.nix
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{ lib }:
|
||||
let
|
||||
inherit (lib) filter head mapAttrs tail;
|
||||
|
||||
# absolutePathComponentsBetween : PathOrString -> PathOrString -> [String]
|
||||
# absolutePathComponentsBetween ancestor descendant
|
||||
#
|
||||
# Returns the path components that form the path from ancestor to descendant.
|
||||
# Will not return ".." components, which is a feature. Throws when ancestor
|
||||
# and descendant arguments aren't in said relation to each other.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# absolutePathComponentsBetween /a /a/b/c == ["b" "c"]
|
||||
# absolutePathComponentsBetween /a/b/c /a/b/c == []
|
||||
absolutePathComponentsBetween =
|
||||
# TODO: port the tests from https://github.com/NixOS/nixpkgs/pull/112083
|
||||
ancestor: descendant:
|
||||
let
|
||||
a' = /. + ancestor;
|
||||
go = d:
|
||||
if a' == d
|
||||
then []
|
||||
else if d == /.
|
||||
then throw "absolutePathComponentsBetween: path ${toString ancestor} is not an ancestor of ${toString descendant}"
|
||||
else go (dirOf d) ++ [(baseNameOf d)];
|
||||
in
|
||||
go (/. + descendant);
|
||||
|
||||
/*
|
||||
Memoize a function that takes a path argument.
|
||||
Example:
|
||||
analyzeTree = dir:
|
||||
let g = memoizePathFunction (p: t: expensiveFunction p t) (p: {}) dir;
|
||||
in presentExpensiveData g;
|
||||
Type:
|
||||
memoizePathFunction :: (Path -> Type -> a) -> (Path -> a) -> Path -> (Path -> a)
|
||||
*/
|
||||
memoize =
|
||||
# Function to memoize
|
||||
f:
|
||||
# What to return when a path does not exist, as a function of the path
|
||||
missing:
|
||||
# Filesystem location below which the returned function is defined. `/.` may be acceptable, but a path closer to the data of interest is better.
|
||||
root:
|
||||
|
||||
# TODO: port the tests from https://github.com/NixOS/nixpkgs/pull/112083
|
||||
|
||||
let
|
||||
makeTree = dir: type: {
|
||||
value = f dir type;
|
||||
inherit type;
|
||||
children =
|
||||
if type == "directory"
|
||||
then mapAttrs
|
||||
(key: type: makeTree (dir + "/${key}") type)
|
||||
(builtins.readDir dir)
|
||||
else {};
|
||||
};
|
||||
|
||||
# This is where the memoization happens
|
||||
tree = makeTree root (
|
||||
# We can't query the type of a store path in Nix without readFileType in
|
||||
# pure mode, so we assume.
|
||||
"directory"
|
||||
);
|
||||
|
||||
lookup = notFound: list: subtree:
|
||||
if list == []
|
||||
then subtree.value
|
||||
else if subtree.children ? ${head list}
|
||||
then lookup notFound (tail list) subtree.children.${head list}
|
||||
else notFound;
|
||||
in
|
||||
path: lookup
|
||||
(missing path)
|
||||
(absolutePathComponentsBetween root path)
|
||||
tree;
|
||||
in
|
||||
{
|
||||
inherit memoize absolutePathComponentsBetween;
|
||||
}
|
||||
|
|
@ -54,6 +54,9 @@ let
|
|||
mkdir 12-empty-dir
|
||||
mkdir 12-not-empty-dir
|
||||
touch 12-not-empty-dir/just-a-regular-file
|
||||
|
||||
mkdir 13-dir-with-ignored-contents
|
||||
touches 13-dir-with-ignored-contents/{foo,bar}
|
||||
); }
|
||||
|
||||
create-tree "$1"
|
||||
|
|
@ -106,6 +109,8 @@ let
|
|||
|
||||
# two bracketed classes in one rule
|
||||
7-brackets/*- [Bb]ackup ([0-9]).rdl
|
||||
|
||||
13-dir-with-ignored-contents/*
|
||||
'';
|
||||
|
||||
ignoresAux = "/9-expected/*filepath\n";
|
||||
|
|
|
|||
0
tests/x.bar
Normal file
0
tests/x.bar
Normal file
0
tests/x.foo
Normal file
0
tests/x.foo
Normal file
0
tests/x.qux
Normal file
0
tests/x.qux
Normal file
Loading…
Add table
Add a link
Reference in a new issue