2014-02-18 21:38:23 +00:00
|
|
|
{- git-annex recent views log
|
|
|
|
-
|
|
|
|
- The most recently accessed view comes first.
|
|
|
|
-
|
|
|
|
- This file is stored locally in .git/annex/, not in the git-annex branch.
|
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2014 Joey Hess <id@joeyh.name>
|
2014-02-18 21:38:23 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Logs.View (
|
|
|
|
currentView,
|
|
|
|
setView,
|
2014-02-19 01:02:27 +00:00
|
|
|
removeView,
|
2014-02-18 21:38:23 +00:00
|
|
|
recentViews,
|
|
|
|
branchView,
|
2014-06-04 18:03:41 +00:00
|
|
|
is_branchView,
|
2014-02-18 21:38:23 +00:00
|
|
|
prop_branchView_legal,
|
|
|
|
) where
|
|
|
|
|
2016-01-20 20:36:33 +00:00
|
|
|
import Annex.Common
|
2014-02-18 21:38:23 +00:00
|
|
|
import Types.View
|
|
|
|
import Types.MetaData
|
|
|
|
import qualified Git
|
|
|
|
import qualified Git.Branch
|
|
|
|
import qualified Git.Ref
|
2014-02-19 05:09:17 +00:00
|
|
|
import Git.Types
|
2014-02-18 21:38:23 +00:00
|
|
|
import Utility.Tmp
|
|
|
|
|
|
|
|
import qualified Data.Set as S
|
|
|
|
import Data.Char
|
|
|
|
|
|
|
|
setView :: View -> Annex ()
|
|
|
|
setView v = do
|
2014-02-19 01:02:27 +00:00
|
|
|
old <- take 99 . filter (/= v) <$> recentViews
|
|
|
|
writeViews (v : old)
|
|
|
|
|
|
|
|
writeViews :: [View] -> Annex ()
|
|
|
|
writeViews l = do
|
2014-02-18 21:38:23 +00:00
|
|
|
f <- fromRepo gitAnnexViewLog
|
2014-02-19 05:09:17 +00:00
|
|
|
liftIO $ viaTmp writeFile f $ unlines $ map show l
|
2014-02-19 01:02:27 +00:00
|
|
|
|
|
|
|
removeView :: View -> Annex ()
|
|
|
|
removeView v = writeViews =<< filter (/= v) <$> recentViews
|
2014-02-18 21:38:23 +00:00
|
|
|
|
|
|
|
recentViews :: Annex [View]
|
|
|
|
recentViews = do
|
|
|
|
f <- fromRepo gitAnnexViewLog
|
2014-02-19 05:09:17 +00:00
|
|
|
liftIO $ mapMaybe readish . lines <$> catchDefaultIO [] (readFile f)
|
2014-02-18 21:38:23 +00:00
|
|
|
|
|
|
|
{- Gets the currently checked out view, if there is one. -}
|
|
|
|
currentView :: Annex (Maybe View)
|
2014-02-19 16:52:47 +00:00
|
|
|
currentView = go =<< inRepo Git.Branch.current
|
2014-02-18 21:38:23 +00:00
|
|
|
where
|
2014-02-19 16:52:47 +00:00
|
|
|
go (Just b) | branchViewPrefix `isPrefixOf` fromRef b =
|
|
|
|
headMaybe . filter (\v -> branchView v == b) <$> recentViews
|
|
|
|
go _ = return Nothing
|
|
|
|
|
|
|
|
branchViewPrefix :: String
|
|
|
|
branchViewPrefix = "refs/heads/views"
|
2014-02-18 21:38:23 +00:00
|
|
|
|
|
|
|
{- Generates a git branch name for a View.
|
|
|
|
-
|
|
|
|
- There is no guarantee that each view gets a unique branch name,
|
|
|
|
- but the branch name is used to express the view as well as possible.
|
|
|
|
-}
|
|
|
|
branchView :: View -> Git.Branch
|
|
|
|
branchView view
|
2014-02-19 16:52:47 +00:00
|
|
|
| null name = Git.Ref branchViewPrefix
|
|
|
|
| otherwise = Git.Ref $ branchViewPrefix ++ "/" ++ name
|
2014-02-18 21:38:23 +00:00
|
|
|
where
|
|
|
|
name = intercalate ";" $ map branchcomp (viewComponents view)
|
|
|
|
branchcomp c
|
add tip about metadata driven views (and more flexible view filtering)
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.
2014-02-19 19:10:18 +00:00
|
|
|
| viewVisible c = branchcomp' c
|
2014-02-18 21:38:23 +00:00
|
|
|
| otherwise = "(" ++ branchcomp' c ++ ")"
|
2014-02-19 21:29:04 +00:00
|
|
|
branchcomp' (ViewComponent metafield viewfilter _) =concat
|
|
|
|
[ forcelegal (fromMetaField metafield)
|
|
|
|
, branchvals viewfilter
|
|
|
|
]
|
2014-03-02 18:53:19 +00:00
|
|
|
branchvals (FilterValues set) = '=' : branchset set
|
|
|
|
branchvals (FilterGlob glob) = '=' : forcelegal glob
|
|
|
|
branchvals (ExcludeValues set) = "!=" ++ branchset set
|
|
|
|
branchset = intercalate ","
|
|
|
|
. map (forcelegal . fromMetaValue)
|
|
|
|
. S.toList
|
2014-02-18 21:38:23 +00:00
|
|
|
forcelegal s
|
|
|
|
| Git.Ref.legal True s = s
|
|
|
|
| otherwise = map (\c -> if isAlphaNum c then c else '_') s
|
|
|
|
|
2014-06-04 18:03:41 +00:00
|
|
|
is_branchView :: Git.Branch -> Bool
|
|
|
|
is_branchView (Ref b)
|
|
|
|
| b == branchViewPrefix = True
|
|
|
|
| otherwise = (branchViewPrefix ++ "/") `isPrefixOf` b
|
|
|
|
|
2014-02-18 21:38:23 +00:00
|
|
|
prop_branchView_legal :: View -> Bool
|
2014-02-19 05:09:17 +00:00
|
|
|
prop_branchView_legal = Git.Ref.legal False . fromRef . branchView
|