dd7b99c860
While writing this documentation, I realized that there needed to be a way to stay in a view like tag=* while adding a filter like tag=work that applies to the same field. So, there are really two ways a view can be refined. It can have a new "field=explicitvalue" filter added to it, which does not change the "shape" of the view, but narrows the files it shows. Or, it can have a new view added, which adds another level of subdirectories. So, added a vfilter command, which takes explicit values to add to the filter, and rejects changes that would change the shape of the view. And, made vadd only accept changes that change the shape of the view. And, changed the View data type slightly; now components that can match multiple metadata values can be visible, or not visible. This commit was sponsored by Stelian Iancu.
90 lines
2.5 KiB
Haskell
90 lines
2.5 KiB
Haskell
{- git-annex command
|
|
-
|
|
- Copyright 2014 Joey Hess <joey@kitenet.net>
|
|
-
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
-}
|
|
|
|
module Command.View where
|
|
|
|
import Common.Annex
|
|
import Command
|
|
import qualified Git
|
|
import qualified Git.Command
|
|
import qualified Git.Ref
|
|
import qualified Git.Branch
|
|
import Types.MetaData
|
|
import Types.View
|
|
import Annex.View
|
|
import Logs.View
|
|
|
|
def :: [Command]
|
|
def = [notBareRepo $ notDirect $
|
|
command "view" paramView seek SectionMetaData "enter a view branch"]
|
|
|
|
seek :: CommandSeek
|
|
seek = withWords start
|
|
|
|
start :: [String] -> CommandStart
|
|
start [] = error "Specify metadata to include in view"
|
|
start params = do
|
|
showStart "view" ""
|
|
view <- mkView params
|
|
go view =<< currentView
|
|
where
|
|
go view Nothing = next $ perform view
|
|
go view (Just v)
|
|
| v == view = stop
|
|
| otherwise = error "Already in a view. Use 'git annex vadd' to further refine this view."
|
|
|
|
perform :: View -> CommandPerform
|
|
perform view = do
|
|
showSideAction "searching"
|
|
next $ checkoutViewBranch view applyView
|
|
|
|
paramView :: String
|
|
paramView = paramPair (paramRepeating "FIELD=VALUE") (paramRepeating "TAG")
|
|
|
|
parseViewParam :: String -> (MetaField, String)
|
|
parseViewParam s = case separate (== '=') s of
|
|
(tag, []) -> (tagMetaField, tag)
|
|
(field, wanted) -> either error (\f -> (f, wanted)) (mkMetaField field)
|
|
|
|
mkView :: [String] -> Annex View
|
|
mkView params = do
|
|
v <- View <$> viewbranch <*> pure []
|
|
return $ fst $ refineView v $
|
|
map parseViewParam $ reverse params
|
|
where
|
|
viewbranch = fromMaybe (error "not on any branch!")
|
|
<$> inRepo Git.Branch.current
|
|
|
|
checkoutViewBranch :: View -> (View -> Annex Git.Branch) -> CommandCleanup
|
|
checkoutViewBranch view mkbranch = do
|
|
oldcwd <- liftIO getCurrentDirectory
|
|
|
|
{- Change to top of repository before creating view branch. -}
|
|
liftIO . setCurrentDirectory =<< fromRepo Git.repoPath
|
|
branch <- mkbranch view
|
|
|
|
showOutput
|
|
ok <- inRepo $ Git.Command.runBool
|
|
[ Param "checkout"
|
|
, Param (Git.fromRef $ Git.Ref.base branch)
|
|
]
|
|
when ok $ do
|
|
setView view
|
|
{- A git repo can easily have empty directories in it,
|
|
- and this pollutes the view, so remove them. -}
|
|
liftIO $ removeemptydirs "."
|
|
unlessM (liftIO $ doesDirectoryExist oldcwd) $ do
|
|
top <- fromRepo Git.repoPath
|
|
showLongNote (cwdmissing top)
|
|
return ok
|
|
where
|
|
removeemptydirs top = mapM_ (tryIO . removeDirectory)
|
|
=<< dirTreeRecursiveSkipping (".git" `isSuffixOf`) top
|
|
cwdmissing top = unlines
|
|
[ "This view does not include the subdirectory you are currently in."
|
|
, "Perhaps you should: cd " ++ top
|
|
]
|