Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
f-f authored Oct 31, 2024
2 parents e5838a0 + c4de1e7 commit 69476be
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
34 changes: 22 additions & 12 deletions src/Spago/Glob.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Control.Monad.Maybe.Trans (runMaybeT)
import Control.Monad.Trans.Class (lift)
import Data.Array as Array
import Data.Filterable (filter)
import Data.Foldable (any, traverse_)
import Data.Foldable (all, any, traverse_)
import Data.String as String
import Data.String as String.CodePoint
import Effect.Aff as Aff
Expand Down Expand Up @@ -101,6 +101,15 @@ fsWalk cwd ignorePatterns includePatterns = Aff.makeAff \cb -> do
canceled <- Ref.new false

let
-- The base of every includePattern
-- The base of a pattern is its longest non-glob prefix.
-- For example: foo/bar/*/*.purs => foo/bar
-- **/spago.yaml => ""
includePatternBases :: Array String
includePatternBases = map (_.base <<< scanPattern) includePatterns

allIncludePatternsHaveBase = all (not <<< String.null) includePatternBases

-- Update the ignoreMatcherRef with the patterns from a .gitignore file
updateIgnoreMatcherWithGitignore :: Entry -> Effect Unit
updateIgnoreMatcherWithGitignore entry = do
Expand All @@ -119,9 +128,17 @@ fsWalk cwd ignorePatterns includePatterns = Aff.makeAff \cb -> do
-- ex. if `includePatterns` is [".spago/p/aff-1.0.0/**/*.purs"],
-- and `gitignored` is ["node_modules", ".spago"],
-- then add "node_modules" to `ignoreMatcher` but not ".spago"
wouldConflictWithSearch matcher = any matcher includePatterns

newMatchers = or $ filter (not <<< wouldConflictWithSearch) gitignored
wouldConflictWithSearch matcher = any matcher includePatternBases

newMatchers :: Array (String -> Boolean)
newMatchers | allIncludePatternsHaveBase = filter (not <<< wouldConflictWithSearch) gitignored
newMatchers = do
-- Some of the include patterns don't have a base,
-- e.g. there is an include pattern like "*/foo/bar" or "**/.spago".
-- In this case, do not attempt to determine whether the gitignore
-- file would exclude some of the target paths. Instead always respect
-- the .gitignore.
gitignored

-- Another possible approach could be to keep a growing array of patterns and
-- regenerate the matcher on every gitignore. We have tried that (see #1234),
Expand All @@ -133,17 +150,10 @@ fsWalk cwd ignorePatterns includePatterns = Aff.makeAff \cb -> do
-- new matchers together, then the whole thing with the previous matcher.
-- This is still prone to stack issues, but we now have a tree so it should
-- not be as dramatic.
addMatcher currentMatcher = or [ currentMatcher, newMatchers ]
addMatcher currentMatcher = or $ Array.cons currentMatcher newMatchers

Ref.modify_ addMatcher ignoreMatcherRef

-- The base of every includePattern
-- The base of a pattern is its longest non-glob prefix.
-- For example: foo/bar/*/*.purs => foo/bar
-- **/spago.yaml => ""
includePatternBases :: Array String
includePatternBases = map (_.base <<< scanPattern) includePatterns

matchesAnyPatternBase :: String -> Boolean
matchesAnyPatternBase relDirPath = any matchesPatternBase includePatternBases
where
Expand Down
5 changes: 5 additions & 0 deletions test/Spago/Glob.purs
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,8 @@ spec = Spec.around globTmpDir do
FS.writeTextFile (Path.concat [ p, "fruits", "right", ".gitignore" ]) hugeGitignore
a <- Glob.gitignoringGlob p [ "fruits/**/apple" ]
Array.sort a `Assert.shouldEqual` [ "fruits/left/apple", "fruits/right/apple" ]

Spec.it "does respect .gitignore even though it might conflict with a search path without base" $ \p -> do
FS.writeTextFile (Path.concat [ p, ".gitignore" ]) "fruits"
a <- Glob.gitignoringGlob p [ "**/apple" ]
Array.sort a `Assert.shouldEqual` []

0 comments on commit 69476be

Please sign in to comment.