webapp: avoid overwriting remote configs when enabling it

Avoid stomping on existing group and preferred content settings
when enabling or combining with an already existing remote.

Two level fix. First, use defaultStandardGroup rather than
setStandardGroup, so if there is an existing configuration in the git-annex
branch, it's not overwritten.

To handle pre-existing ssh remotes (including gcrypt), a second level is
needed, because before syncing with the remote, it's configuration won't be
available locally. (And syncing could take a long time.) So, in this case,
keep track of whether the remote is being created or enabled, and only set
configs when creating it.

This commit was sponsored by Anders Lannerback.
This commit is contained in:
Joey Hess 2014-05-30 14:03:04 -04:00
parent 7089e282b5
commit 9eaabf0382
6 changed files with 52 additions and 29 deletions

View file

@ -339,7 +339,7 @@ getFinishAddDriveR drive = go
(Git.Config.boolConfig True) (Git.Config.boolConfig True)
(u, r) <- a isnew (u, r) <- a isnew
when isnew $ when isnew $
liftAnnex $ setStandardGroup u TransferGroup liftAnnex $ defaultStandardGroup u TransferGroup
liftAssistant $ immediateSyncRemote r liftAssistant $ immediateSyncRemote r
redirect $ EditNewRepositoryR u redirect $ EditNewRepositoryR u
mountpoint = T.unpack (mountPoint drive) mountpoint = T.unpack (mountPoint drive)
@ -471,7 +471,7 @@ initRepo' :: Maybe String -> Maybe StandardGroup -> Annex ()
initRepo' desc mgroup = unlessM isInitialized $ do initRepo' desc mgroup = unlessM isInitialized $ do
initialize desc initialize desc
u <- getUUID u <- getUUID
maybe noop (setStandardGroup u) mgroup maybe noop (defaultStandardGroup u) mgroup
{- Ensure branch gets committed right away so it is {- Ensure branch gets committed right away so it is
- available for merging immediately. -} - available for merging immediately. -}
Annex.Branch.commit "update" Annex.Branch.commit "update"

View file

@ -61,6 +61,10 @@ data AuthMethod
| ExistingSshKey | ExistingSshKey
deriving (Eq, Show) deriving (Eq, Show)
-- Is a repository a new one that's being created, or did it already exist
-- and is just being added.
data RepoStatus = NewRepo | ExistingRepo
{- SshInput is only used for applicative form prompting, this converts {- SshInput is only used for applicative form prompting, this converts
- the result of such a form into a SshData. -} - the result of such a form into a SshData. -}
mkSshData :: SshInput -> SshData mkSshData :: SshInput -> SshData
@ -425,9 +429,7 @@ getConfirmSshR sshdata u
m <- liftAnnex readRemoteLog m <- liftAnnex readRemoteLog
case M.lookup "type" =<< M.lookup u m of case M.lookup "type" =<< M.lookup u m of
Just "gcrypt" -> combineExistingGCrypt sshdata' u Just "gcrypt" -> combineExistingGCrypt sshdata' u
-- This handles enabling git repositories _ -> makeSshRepo ExistingRepo sshdata'
-- that already exist.
_ -> makeSshRepo sshdata'
{- The user has confirmed they want to combine with a ssh repository, {- The user has confirmed they want to combine with a ssh repository,
- which is not known to us. So it might be using gcrypt. -} - which is not known to us. So it might be using gcrypt. -}
@ -435,7 +437,7 @@ getCombineSshR :: SshData -> Handler Html
getCombineSshR sshdata = prepSsh False sshdata $ \sshdata' -> getCombineSshR sshdata = prepSsh False sshdata $ \sshdata' ->
sshConfigurator $ sshConfigurator $
checkExistingGCrypt sshdata' $ checkExistingGCrypt sshdata' $
void $ liftH $ makeSshRepo sshdata' void $ liftH $ makeSshRepo ExistingRepo sshdata'
getRetrySshR :: SshData -> Handler () getRetrySshR :: SshData -> Handler ()
getRetrySshR sshdata = do getRetrySshR sshdata = do
@ -444,10 +446,10 @@ getRetrySshR sshdata = do
{- Making a new git repository. -} {- Making a new git repository. -}
getMakeSshGitR :: SshData -> Handler Html getMakeSshGitR :: SshData -> Handler Html
getMakeSshGitR sshdata = prepSsh True sshdata makeSshRepo getMakeSshGitR sshdata = prepSsh True sshdata (makeSshRepo NewRepo)
getMakeSshRsyncR :: SshData -> Handler Html getMakeSshRsyncR :: SshData -> Handler Html
getMakeSshRsyncR sshdata = prepSsh False (rsyncOnly sshdata) makeSshRepo getMakeSshRsyncR sshdata = prepSsh False (rsyncOnly sshdata) (makeSshRepo NewRepo)
rsyncOnly :: SshData -> SshData rsyncOnly :: SshData -> SshData
rsyncOnly sshdata = sshdata { sshCapabilities = [RsyncCapable] } rsyncOnly sshdata = sshdata { sshCapabilities = [RsyncCapable] }
@ -456,7 +458,7 @@ getMakeSshGCryptR :: SshData -> RepoKey -> Handler Html
getMakeSshGCryptR sshdata NoRepoKey = whenGcryptInstalled $ getMakeSshGCryptR sshdata NoRepoKey = whenGcryptInstalled $
withNewSecretKey $ getMakeSshGCryptR sshdata . RepoKey withNewSecretKey $ getMakeSshGCryptR sshdata . RepoKey
getMakeSshGCryptR sshdata (RepoKey keyid) = whenGcryptInstalled $ getMakeSshGCryptR sshdata (RepoKey keyid) = whenGcryptInstalled $
prepSsh False sshdata $ makeGCryptRepo keyid prepSsh False sshdata $ makeGCryptRepo NewRepo keyid
{- Detect if the user entered a location with an existing, known {- Detect if the user entered a location with an existing, known
- gcrypt repository, and enable it. Otherwise, runs the action. -} - gcrypt repository, and enable it. Otherwise, runs the action. -}
@ -523,10 +525,10 @@ prepSsh' needsinit origsshdata sshdata keypair a = sshSetup (mkSshInput origsshd
] ]
rsynconly = onlyCapability origsshdata RsyncCapable rsynconly = onlyCapability origsshdata RsyncCapable
makeSshRepo :: SshData -> Handler Html makeSshRepo :: RepoStatus -> SshData -> Handler Html
makeSshRepo sshdata makeSshRepo rs sshdata
| onlyCapability sshdata RsyncCapable = setupCloudRemote TransferGroup Nothing mk | onlyCapability sshdata RsyncCapable = setupCloudRemote TransferGroup Nothing mk
| otherwise = makeSshRepoConnection mk setup | otherwise = makeSshRepoConnection rs mk setup
where where
mk = makeSshRemote sshdata mk = makeSshRemote sshdata
-- Record the location of the ssh remote in the remote log, so it -- Record the location of the ssh remote in the remote log, so it
@ -539,16 +541,19 @@ makeSshRepo sshdata
M.insert "name" (fromMaybe (Remote.name r) (M.lookup "name" c)) c M.insert "name" (fromMaybe (Remote.name r) (M.lookup "name" c)) c
configSet (Remote.uuid r) c' configSet (Remote.uuid r) c'
makeSshRepoConnection :: Annex RemoteName -> (Remote -> Annex ()) -> Handler Html makeSshRepoConnection :: RepoStatus -> Annex RemoteName -> (Remote -> Annex ()) -> Handler Html
makeSshRepoConnection mk setup = setupRemote postsetup TransferGroup Nothing mk makeSshRepoConnection rs mk setup = setupRemote postsetup mgroup Nothing mk
where where
mgroup = case rs of
NewRepo -> Just TransferGroup
ExistingRepo -> Nothing
postsetup r = do postsetup r = do
liftAssistant $ sendRemoteControl RELOAD liftAssistant $ sendRemoteControl RELOAD
liftAnnex $ setup r liftAnnex $ setup r
redirect $ EditNewRepositoryR (Remote.uuid r) redirect $ EditNewRepositoryR (Remote.uuid r)
makeGCryptRepo :: KeyId -> SshData -> Handler Html makeGCryptRepo :: RepoStatus -> KeyId -> SshData -> Handler Html
makeGCryptRepo keyid sshdata = makeSshRepoConnection mk (const noop) makeGCryptRepo rs keyid sshdata = makeSshRepoConnection rs mk (const noop)
where where
mk = makeGCryptRemote (sshRepoName sshdata) (genSshUrl sshdata) keyid mk = makeGCryptRemote (sshRepoName sshdata) (genSshUrl sshdata) keyid
@ -591,21 +596,22 @@ postAddRsyncNetR = do
$(widgetFile "configurators/rsync.net/encrypt") $(widgetFile "configurators/rsync.net/encrypt")
getMakeRsyncNetSharedR :: SshData -> Handler Html getMakeRsyncNetSharedR :: SshData -> Handler Html
getMakeRsyncNetSharedR = makeSshRepo . rsyncOnly getMakeRsyncNetSharedR = makeSshRepo NewRepo . rsyncOnly
{- Make a gcrypt special remote on rsync.net. -} {- Make a new gcrypt special remote on rsync.net. -}
getMakeRsyncNetGCryptR :: SshData -> RepoKey -> Handler Html getMakeRsyncNetGCryptR :: SshData -> RepoKey -> Handler Html
getMakeRsyncNetGCryptR sshdata NoRepoKey = whenGcryptInstalled $ getMakeRsyncNetGCryptR sshdata NoRepoKey = whenGcryptInstalled $
withNewSecretKey $ getMakeRsyncNetGCryptR sshdata . RepoKey withNewSecretKey $ getMakeRsyncNetGCryptR sshdata . RepoKey
getMakeRsyncNetGCryptR sshdata (RepoKey keyid) = whenGcryptInstalled $ getMakeRsyncNetGCryptR sshdata (RepoKey keyid) = whenGcryptInstalled $
sshSetup (mkSshInput sshdata) [sshhost, gitinit] Nothing $ makeGCryptRepo keyid sshdata sshSetup (mkSshInput sshdata) [sshhost, gitinit] Nothing $
makeGCryptRepo NewRepo keyid sshdata
where where
sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata) sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata)
gitinit = "git init --bare " ++ T.unpack (sshDirectory sshdata) gitinit = "git init --bare " ++ T.unpack (sshDirectory sshdata)
enableRsyncNet :: SshInput -> String -> Handler Html enableRsyncNet :: SshInput -> String -> Handler Html
enableRsyncNet sshinput reponame = enableRsyncNet sshinput reponame =
prepRsyncNet sshinput reponame $ makeSshRepo . rsyncOnly prepRsyncNet sshinput reponame $ makeSshRepo ExistingRepo . rsyncOnly
enableRsyncNetGCrypt :: SshInput -> RemoteName -> Handler Html enableRsyncNetGCrypt :: SshInput -> RemoteName -> Handler Html
enableRsyncNetGCrypt sshinput reponame = enableRsyncNetGCrypt sshinput reponame =

View file

@ -31,13 +31,15 @@ import Utility.Yesod
- This includes displaying the connectionNeeded nudge if appropariate. - This includes displaying the connectionNeeded nudge if appropariate.
-} -}
setupCloudRemote :: StandardGroup -> Maybe Cost -> Annex RemoteName -> Handler a setupCloudRemote :: StandardGroup -> Maybe Cost -> Annex RemoteName -> Handler a
setupCloudRemote = setupRemote $ redirect . EditNewCloudRepositoryR . Remote.uuid setupCloudRemote = setupRemote postsetup . Just
where
postsetup = redirect . EditNewCloudRepositoryR . Remote.uuid
setupRemote :: (Remote -> Handler a) -> StandardGroup -> Maybe Cost -> Annex RemoteName -> Handler a setupRemote :: (Remote -> Handler a) -> Maybe StandardGroup -> Maybe Cost -> Annex RemoteName -> Handler a
setupRemote postsetup defaultgroup mcost getname = do setupRemote postsetup mgroup mcost getname = do
r <- liftAnnex $ addRemote getname r <- liftAnnex $ addRemote getname
liftAnnex $ do liftAnnex $ do
setStandardGroup (Remote.uuid r) defaultgroup maybe noop (defaultStandardGroup (Remote.uuid r)) mgroup
maybe noop (Config.setRemoteCost (Remote.repo r)) mcost maybe noop (Config.setRemoteCost (Remote.repo r)) mcost
liftAssistant $ syncRemote r liftAssistant $ syncRemote r
postsetup r postsetup r

View file

@ -18,6 +18,7 @@ module Logs.PreferredContent (
groupPreferredContentMapRaw, groupPreferredContentMapRaw,
checkPreferredContentExpression, checkPreferredContentExpression,
setStandardGroup, setStandardGroup,
defaultStandardGroup,
preferredRequiredMapsLoad, preferredRequiredMapsLoad,
) where ) where
@ -133,10 +134,20 @@ checkPreferredContentExpression expr = case parsedToMatcher tokens of
tokens = exprParser matchAll matchAll emptyGroupMap M.empty Nothing expr tokens = exprParser matchAll matchAll emptyGroupMap M.empty Nothing expr
{- Puts a UUID in a standard group, and sets its preferred content to use {- Puts a UUID in a standard group, and sets its preferred content to use
- the standard expression for that group, unless something is already set. -} - the standard expression for that group (unless preferred content is
- already set). -}
setStandardGroup :: UUID -> StandardGroup -> Annex () setStandardGroup :: UUID -> StandardGroup -> Annex ()
setStandardGroup u g = do setStandardGroup u g = do
groupSet u $ S.singleton $ fromStandardGroup g groupSet u $ S.singleton $ fromStandardGroup g
m <- preferredContentMap unlessM (isJust . M.lookup u <$> preferredContentMap) $
unless (isJust $ M.lookup u m) $
preferredContentSet u "standard" preferredContentSet u "standard"
{- Avoids overwriting the UUID's standard group or preferred content
- when it's already been configured. -}
defaultStandardGroup :: UUID -> StandardGroup -> Annex ()
defaultStandardGroup u g =
unlessM (hasgroup <||> haspc) $
setStandardGroup u g
where
hasgroup = not . S.null <$> lookupGroups u
haspc = isJust . M.lookup u <$> preferredContentMap

3
debian/changelog vendored
View file

@ -4,8 +4,7 @@ git-annex (5.20140530) UNRELEASED; urgency=medium
group and preferred content to be set in the current repository, group and preferred content to be set in the current repository,
even when not combining. even when not combining.
* webapp: Avoid stomping on existing group and preferred content settings * webapp: Avoid stomping on existing group and preferred content settings
when adding a local repository (or removable drive repository) that when enabling or combining with an already existing remote.
already exists.
-- Joey Hess <joeyh@debian.org> Thu, 29 May 2014 20:10:59 -0400 -- Joey Hess <joeyh@debian.org> Thu, 29 May 2014 20:10:59 -0400

View file

@ -9,3 +9,8 @@ may have the same problems. Didn't check yet.
> Fixed for local repos and repos on removable drives. Still open for > Fixed for local repos and repos on removable drives. Still open for
> ssh remotes (incl gcrypt). --[[Joey]] > ssh remotes (incl gcrypt). --[[Joey]]
>> Fixed for ssh (including gcrypt) too.
>>
>> Also affected enabling existing special remotes, like webdav; that's
>> also fixed. [[done]] --[[Joey]]