git-annex/Assistant/WebApp/Configurators/Edit.hs

244 lines
8.4 KiB
Haskell
Raw Normal View History

{- git-annex assistant webapp configurator for editing existing repos
-
- Copyright 2012 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
2013-06-05 01:02:09 +00:00
{-# LANGUAGE CPP, QuasiQuotes, TemplateHaskell, OverloadedStrings #-}
module Assistant.WebApp.Configurators.Edit where
2012-11-25 04:26:46 +00:00
import Assistant.WebApp.Common
import Assistant.WebApp.Gpg
import Assistant.DaemonStatus
import Assistant.MakeRemote (uniqueRemoteName)
import Assistant.WebApp.Configurators.XMPP (xmppNeeded)
import Assistant.ScanRemotes
import Assistant.Sync
import qualified Assistant.WebApp.Configurators.AWS as AWS
import qualified Assistant.WebApp.Configurators.IA as IA
#ifdef WITH_S3
import qualified Remote.S3 as S3
#endif
import qualified Remote
import qualified Types.Remote as Remote
import qualified Remote.List as Remote
import Logs.UUID
import Logs.Group
import Logs.PreferredContent
import Logs.Remote
import Types.StandardGroups
import qualified Git
import qualified Git.Command
import qualified Git.Config
import qualified Annex
import Git.Remote
import Remote.Helper.Encryptable (extractCipher)
import Types.Crypto
import Utility.Gpg
import qualified Data.Text as T
import qualified Data.Map as M
2012-10-10 20:23:41 +00:00
import qualified Data.Set as S
data RepoGroup = RepoGroupCustom String | RepoGroupStandard StandardGroup
deriving (Show, Eq)
data RepoConfig = RepoConfig
{ repoName :: Text
, repoDescription :: Maybe Text
2012-10-10 20:23:41 +00:00
, repoGroup :: RepoGroup
2013-04-26 17:00:14 +00:00
, repoAssociatedDirectory :: Maybe Text
, repoSyncable :: Bool
}
deriving (Show)
getRepoConfig :: UUID -> Maybe Remote -> Annex RepoConfig
2013-04-26 17:00:14 +00:00
getRepoConfig uuid mremote = do
groups <- lookupGroups uuid
remoteconfig <- M.lookup uuid <$> readRemoteLog
let (repogroup, associateddirectory) = case getStandardGroup groups of
Nothing -> (RepoGroupCustom $ unwords $ S.toList groups, Nothing)
Just g -> (RepoGroupStandard g, associatedDirectory remoteconfig g)
2013-10-02 05:06:59 +00:00
description <- fmap T.pack . M.lookup uuid <$> uuidMap
2013-04-26 17:00:14 +00:00
syncable <- case mremote of
Just r -> return $ remoteAnnexSync $ Remote.gitconfig r
Nothing -> annexAutoCommit <$> Annex.getGitConfig
2013-04-26 17:00:14 +00:00
return $ RepoConfig
(T.pack $ maybe "here" Remote.name mremote)
description
repogroup
(T.pack <$> associateddirectory)
syncable
setRepoConfig :: UUID -> Maybe Remote -> RepoConfig -> RepoConfig -> Handler ()
setRepoConfig uuid mremote oldc newc = do
when descriptionChanged $ liftAnnex $ do
maybe noop (describeUUID uuid . T.unpack) (repoDescription newc)
void uuidMapLoad
when nameChanged $ do
liftAnnex $ do
name <- fromRepo $ uniqueRemoteName (legalName newc) 0
{- git remote rename expects there to be a
- remote.<name>.fetch, and exits nonzero if
- there's not. Special remotes don't normally
- have that, and don't use it. Temporarily add
- it if it's missing. -}
let remotefetch = "remote." ++ T.unpack (repoName oldc) ++ ".fetch"
needfetch <- isNothing <$> fromRepo (Git.Config.getMaybe remotefetch)
when needfetch $
inRepo $ Git.Command.run
[Param "config", Param remotefetch, Param ""]
inRepo $ Git.Command.run
[ Param "remote"
, Param "rename"
, Param $ T.unpack $ repoName oldc
, Param name
]
2013-10-02 05:06:59 +00:00
void Remote.remoteListRefresh
liftAssistant updateSyncRemotes
2013-04-26 17:00:14 +00:00
when associatedDirectoryChanged $ case repoAssociatedDirectory newc of
Nothing -> noop
Just t
| T.null t -> noop
| otherwise -> liftAnnex $ do
let dir = takeBaseName $ T.unpack t
m <- readRemoteLog
case M.lookup uuid m of
Nothing -> noop
Just remoteconfig -> configSet uuid $
M.insert "preferreddir" dir remoteconfig
when groupChanged $ do
liftAnnex $ case repoGroup newc of
RepoGroupStandard g -> setStandardGroup uuid g
RepoGroupCustom s -> groupSet uuid $ S.fromList $ words s
{- Enabling syncing will cause a scan,
- so avoid queueing a duplicate scan. -}
when (repoSyncable newc && not syncableChanged) $ liftAssistant $
case mremote of
2013-10-02 05:06:59 +00:00
Just remote -> addScanRemotes True [remote]
Nothing -> addScanRemotes True
=<< syncDataRemotes <$> getDaemonStatus
when syncableChanged $
liftAssistant $ changeSyncable mremote (repoSyncable newc)
where
syncableChanged = repoSyncable oldc /= repoSyncable newc
2013-04-26 17:00:14 +00:00
associatedDirectoryChanged = repoAssociatedDirectory oldc /= repoAssociatedDirectory newc
groupChanged = repoGroup oldc /= repoGroup newc
nameChanged = isJust mremote && legalName oldc /= legalName newc
descriptionChanged = repoDescription oldc /= repoDescription newc
legalName = makeLegalName . T.unpack . repoName
editRepositoryAForm :: Bool -> RepoConfig -> MkAForm RepoConfig
editRepositoryAForm ishere def = RepoConfig
<$> areq (if ishere then readonlyTextField else textField)
"Name" (Just $ repoName def)
<*> aopt textField "Description" (Just $ repoDescription def)
<*> areq (selectFieldList groups `withNote` help) "Repository group" (Just $ repoGroup def)
2013-04-26 17:00:14 +00:00
<*> associateddirectory
<*> areq checkBoxField "Syncing enabled" (Just $ repoSyncable def)
2012-10-31 06:34:03 +00:00
where
groups = customgroups ++ standardgroups
2012-10-31 06:34:03 +00:00
standardgroups :: [(Text, RepoGroup)]
2013-04-26 17:00:14 +00:00
standardgroups = map (\g -> (T.pack $ descStandardGroup g , RepoGroupStandard g))
2012-10-31 06:34:03 +00:00
[minBound :: StandardGroup .. maxBound :: StandardGroup]
customgroups :: [(Text, RepoGroup)]
customgroups = case repoGroup def of
RepoGroupCustom s -> [(T.pack s, RepoGroupCustom s)]
_ -> []
help = [whamlet|<a href="@{RepoGroupR}">What's this?</a>|]
2013-04-26 17:00:14 +00:00
associateddirectory = case repoAssociatedDirectory def of
2013-04-26 19:06:18 +00:00
Nothing -> aopt hiddenField "" Nothing
2013-04-26 17:00:14 +00:00
Just d -> aopt textField "Associated directory" (Just $ Just d)
getEditRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
getEditRepositoryR = postEditRepositoryR
postEditRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
postEditRepositoryR = editForm False
getEditNewRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
getEditNewRepositoryR = postEditNewRepositoryR
postEditNewRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
postEditNewRepositoryR = editForm True
getEditNewCloudRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
getEditNewCloudRepositoryR = postEditNewCloudRepositoryR
postEditNewCloudRepositoryR :: UUID -> Handler Html
2013-03-16 22:48:23 +00:00
postEditNewCloudRepositoryR uuid = xmppNeeded >> editForm True uuid
editForm :: Bool -> UUID -> Handler Html
editForm new uuid = page "Edit repository" (Just Configuration) $ do
mremote <- liftAnnex $ Remote.remoteFromUUID uuid
curr <- liftAnnex $ getRepoConfig uuid mremote
2013-04-26 17:00:14 +00:00
liftAnnex $ checkAssociatedDirectory curr mremote
((result, form), enctype) <- liftH $
runFormPostNoToken $ renderBootstrap $ editRepositoryAForm (isNothing mremote) curr
case result of
FormSuccess input -> liftH $ do
setRepoConfig uuid mremote curr input
2013-04-26 17:00:14 +00:00
liftAnnex $ checkAssociatedDirectory input mremote
redirect DashboardR
_ -> do
let istransfer = repoGroup curr == RepoGroupStandard TransferGroup
config <- liftAnnex $ M.lookup uuid <$> readRemoteLog
let repoInfo = getRepoInfo mremote config
let repoEncryption = getRepoEncryption mremote config
$(widgetFile "configurators/editrepository")
2013-04-26 17:00:14 +00:00
{- Makes any directory associated with the repository. -}
checkAssociatedDirectory :: RepoConfig -> Maybe Remote -> Annex ()
checkAssociatedDirectory _ Nothing = noop
checkAssociatedDirectory cfg (Just r) = do
repoconfig <- M.lookup (Remote.uuid r) <$> readRemoteLog
case repoGroup cfg of
RepoGroupStandard gr -> case associatedDirectory repoconfig gr of
Just d -> inRepo $ \g ->
2013-04-26 03:44:55 +00:00
createDirectoryIfMissing True $
Git.repoPath g </> d
Nothing -> noop
_ -> noop
getRepoInfo :: Maybe Remote.Remote -> Maybe Remote.RemoteConfig -> Widget
getRepoInfo (Just r) (Just c) = case M.lookup "type" c of
Just "S3"
#ifdef WITH_S3
| S3.isIA c -> IA.getRepoInfo c
#endif
| otherwise -> AWS.getRepoInfo c
Just t
| t /= "git" -> [whamlet|#{t} remote|]
_ -> getGitRepoInfo $ Remote.repo r
getRepoInfo (Just r) _ = getRepoInfo (Just r) (Just $ Remote.config r)
getRepoInfo _ _ = [whamlet|git repository|]
getGitRepoInfo :: Git.Repo -> Widget
getGitRepoInfo r = do
let loc = Git.repoLocation r
[whamlet|git repository located at <tt>#{loc}</tt>|]
getRepoEncryption :: Maybe Remote.Remote -> Maybe Remote.RemoteConfig -> Widget
getRepoEncryption (Just _) (Just c) = case extractCipher c of
Nothing ->
[whamlet|not encrypted|]
(Just (SharedCipher _)) ->
[whamlet|encrypted: encryption key stored in git repository|]
(Just (EncryptedCipher _ _ (KeyIds { keyIds = ks }))) -> do
knownkeys <- liftIO secretKeys
[whamlet|
encrypted using gpg key:
<ul style="list-style: none">
$forall k <- ks
<li>
^{gpgKeyDisplay k (M.lookup k knownkeys)}
|]
getRepoEncryption _ _ = return () -- local repo