summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2014-02-19 01:28:48 -0400
committerGravatar Joey Hess <joey@kitenet.net>2014-02-19 01:28:48 -0400
commitbfe8e2641e67c69020e89995fec7dfbc28d2f752 (patch)
treeaf4cbe32d4147e1e5bda835bfa983def5b4e478b
parent51c12a76ef54affaf9428232fde4f2c3e30e7488 (diff)
reject views with too many nested subdirs
-rw-r--r--Annex/View.hs30
1 files changed, 18 insertions, 12 deletions
diff --git a/Annex/View.hs b/Annex/View.hs
index cc2aad5b9..66ae76f75 100644
--- a/Annex/View.hs
+++ b/Annex/View.hs
@@ -35,6 +35,20 @@ data ViewChange = Unchanged | Narrowing | Widening
matchGlob :: String -> String -> Bool
matchGlob glob val = wildCheckCase glob val
+{- Each multivalued ViewFilter in a view results in another level of
+ - subdirectory nesting. When a file matches multiple ways, it will appear
+ - in multiple subdirectories. This means there is a bit of an exponential
+ - blowup with a single file appearing in a crazy number of places!
+ -
+ - Capping the view size to 5 is reasonable; why wants to dig
+ - through 5+ levels of subdirectories to find anything?
+ -}
+viewTooLarge :: View -> Bool
+viewTooLarge view = visibleViewSize view > 5
+
+visibleViewSize :: View -> Int
+visibleViewSize = length . filter (multiValue . viewFilter) . viewComponents
+
{- Updates a view, adding a new field to filter on (Narrowing),
- or allowing a new value in an existing field (Widening). -}
refineView :: View -> MetaField -> String -> (View, ViewChange)
@@ -42,7 +56,10 @@ refineView view field wanted
| field `elem` (map viewField components) =
let (components', viewchanges) = runWriter $ mapM updatefield components
in (view { viewComponents = components' }, maximum viewchanges)
- | otherwise = (view { viewComponents = ViewComponent field viewfilter : components }, Narrowing)
+ | otherwise = let view' = view { viewComponents = ViewComponent field viewfilter : components }
+ in if viewTooLarge view'
+ then error $ "View is too large (" ++ show (visibleViewSize view') ++ " levels of subdirectories)"
+ else (view', Narrowing)
where
components = viewComponents view
viewfilter
@@ -86,17 +103,6 @@ combineViewFilter (FilterGlob old) newglob@(FilterGlob new)
| matchGlob old new = (newglob, Narrowing)
| otherwise = (newglob, Widening)
-{- Each multivalued ViewFilter in a view results in another level of
- - subdirectory nesting. When a file matches multiple ways, it will appear
- - in multiple subdirectories. This means there is a bit of an exponential
- - blowup with a single file appearing in a crazy number of places!
- -
- - Capping the view size to 5 is reasonable; why wants to dig
- - through 5+ levels of subdirectories to find anything?
- -}
-viewTooLarge :: View -> Bool
-viewTooLarge view = length (filter (multiValue . viewFilter) (viewComponents view)) > 5
-
{- Checks if metadata matches a filter, and if so returns the value,
- or values that match. -}
matchFilter :: MetaData -> ViewComponent -> Maybe [MetaValue]