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

View file

@ -61,6 +61,10 @@ data AuthMethod
| ExistingSshKey
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
- the result of such a form into a SshData. -}
mkSshData :: SshInput -> SshData
@ -425,9 +429,7 @@ getConfirmSshR sshdata u
m <- liftAnnex readRemoteLog
case M.lookup "type" =<< M.lookup u m of
Just "gcrypt" -> combineExistingGCrypt sshdata' u
-- This handles enabling git repositories
-- that already exist.
_ -> makeSshRepo sshdata'
_ -> makeSshRepo ExistingRepo sshdata'
{- The user has confirmed they want to combine with a ssh repository,
- 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' ->
sshConfigurator $
checkExistingGCrypt sshdata' $
void $ liftH $ makeSshRepo sshdata'
void $ liftH $ makeSshRepo ExistingRepo sshdata'
getRetrySshR :: SshData -> Handler ()
getRetrySshR sshdata = do
@ -444,10 +446,10 @@ getRetrySshR sshdata = do
{- Making a new git repository. -}
getMakeSshGitR :: SshData -> Handler Html
getMakeSshGitR sshdata = prepSsh True sshdata makeSshRepo
getMakeSshGitR sshdata = prepSsh True sshdata (makeSshRepo NewRepo)
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 { sshCapabilities = [RsyncCapable] }
@ -456,7 +458,7 @@ getMakeSshGCryptR :: SshData -> RepoKey -> Handler Html
getMakeSshGCryptR sshdata NoRepoKey = whenGcryptInstalled $
withNewSecretKey $ getMakeSshGCryptR sshdata . RepoKey
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
- 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
makeSshRepo :: SshData -> Handler Html
makeSshRepo sshdata
makeSshRepo :: RepoStatus -> SshData -> Handler Html
makeSshRepo rs sshdata
| onlyCapability sshdata RsyncCapable = setupCloudRemote TransferGroup Nothing mk
| otherwise = makeSshRepoConnection mk setup
| otherwise = makeSshRepoConnection rs mk setup
where
mk = makeSshRemote sshdata
-- 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
configSet (Remote.uuid r) c'
makeSshRepoConnection :: Annex RemoteName -> (Remote -> Annex ()) -> Handler Html
makeSshRepoConnection mk setup = setupRemote postsetup TransferGroup Nothing mk
makeSshRepoConnection :: RepoStatus -> Annex RemoteName -> (Remote -> Annex ()) -> Handler Html
makeSshRepoConnection rs mk setup = setupRemote postsetup mgroup Nothing mk
where
mgroup = case rs of
NewRepo -> Just TransferGroup
ExistingRepo -> Nothing
postsetup r = do
liftAssistant $ sendRemoteControl RELOAD
liftAnnex $ setup r
redirect $ EditNewRepositoryR (Remote.uuid r)
makeGCryptRepo :: KeyId -> SshData -> Handler Html
makeGCryptRepo keyid sshdata = makeSshRepoConnection mk (const noop)
makeGCryptRepo :: RepoStatus -> KeyId -> SshData -> Handler Html
makeGCryptRepo rs keyid sshdata = makeSshRepoConnection rs mk (const noop)
where
mk = makeGCryptRemote (sshRepoName sshdata) (genSshUrl sshdata) keyid
@ -591,21 +596,22 @@ postAddRsyncNetR = do
$(widgetFile "configurators/rsync.net/encrypt")
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 NoRepoKey = whenGcryptInstalled $
withNewSecretKey $ getMakeRsyncNetGCryptR sshdata . RepoKey
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
sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata)
gitinit = "git init --bare " ++ T.unpack (sshDirectory sshdata)
enableRsyncNet :: SshInput -> String -> Handler Html
enableRsyncNet sshinput reponame =
prepRsyncNet sshinput reponame $ makeSshRepo . rsyncOnly
prepRsyncNet sshinput reponame $ makeSshRepo ExistingRepo . rsyncOnly
enableRsyncNetGCrypt :: SshInput -> RemoteName -> Handler Html
enableRsyncNetGCrypt sshinput reponame =

View file

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

View file

@ -18,6 +18,7 @@ module Logs.PreferredContent (
groupPreferredContentMapRaw,
checkPreferredContentExpression,
setStandardGroup,
defaultStandardGroup,
preferredRequiredMapsLoad,
) where
@ -133,10 +134,20 @@ checkPreferredContentExpression expr = case parsedToMatcher tokens of
tokens = exprParser matchAll matchAll emptyGroupMap M.empty Nothing expr
{- 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 u g = do
groupSet u $ S.singleton $ fromStandardGroup g
m <- preferredContentMap
unless (isJust $ M.lookup u m) $
unlessM (isJust . M.lookup u <$> preferredContentMap) $
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,
even when not combining.
* webapp: Avoid stomping on existing group and preferred content settings
when adding a local repository (or removable drive repository) that
already exists.
when enabling or combining with an already existing remote.
-- 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
> 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]]