--- Begin Message ---
Source: haskell-dav
Severity: normal
Tags: patch
Please apply the two attached patches, which add stuff git-annex needs
to use DAV more efficiently.
--
see shy jo
From e9cc0657853024d32eb2c5a62d8e8a44882fe018 Mon Sep 17 00:00:00 2001
From: Joey Hess <[email protected]>
Date: Wed, 6 Aug 2014 16:16:44 -0400
Subject: [PATCH 1/2] add withDAVContext and runDAVContext
The use case for this is that I have code that cannot run in the DAV monad,
but I want it to run multiple DAV operations while reusing the context,
particularly the http manager's open connection.
---
Network/Protocol/HTTP/DAV.hs | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/Network/Protocol/HTTP/DAV.hs b/Network/Protocol/HTTP/DAV.hs
index c8d76ea..06d1ee9 100644
--- a/Network/Protocol/HTTP/DAV.hs
+++ b/Network/Protocol/HTTP/DAV.hs
@@ -24,6 +24,8 @@
module Network.Protocol.HTTP.DAV (
DAVT(..)
, evalDAVT
+ , withDAVContext
+ , runDAVContext
, setCreds
, setDepth
, setResponseTimeout
@@ -56,7 +58,7 @@ import Network.Protocol.HTTP.DAV.TH
import Control.Applicative (liftA2, Applicative)
import Control.Error (EitherT(..))
-import Control.Exception.Lifted (catchJust, finally, bracketOnError)
+import Control.Exception.Lifted (catchJust, finally, bracket, bracketOnError)
import Control.Lens ((^.), (.=), (%=))
import Control.Monad (liftM, liftM2, when, MonadPlus)
import Control.Monad.Base (MonadBase(..))
@@ -64,7 +66,7 @@ import Control.Monad.Error (MonadError)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans (lift, MonadTrans)
import Control.Monad.IO.Class (liftIO, MonadIO)
-import Control.Monad.State (evalStateT, get, MonadState, StateT)
+import Control.Monad.State (evalStateT, runStateT, get, MonadState, StateT)
import Control.Monad.Trans.Control (MonadBaseControl(..))
import qualified Data.ByteString as B
@@ -95,13 +97,29 @@ instance MonadBaseControl b m => MonadBaseControl b (DAVT m) where
instance MonadTrans DAVT where
lift = DAVT . lift . lift
-evalDAVT :: MonadIO m => String -> DAVT m a -> m (Either String a)
+type DAVURL = String
+
+evalDAVT :: MonadIO m => DAVURL -> DAVT m a -> m (Either String a)
evalDAVT u f = do
+ ctx <- mkDAVContext u
+ r <- (evalStateT . runEitherT . runDAVT) f ctx
+ closeDAVContext ctx
+ return r
+
+mkDAVContext :: MonadIO m => DAVURL -> m DAVContext
+mkDAVContext u = liftIO $ do
mgr <- liftIO $ newManager tlsManagerSettings
req <- liftIO $ parseUrl u
- r <- (evalStateT . runEitherT . runDAVT) f $ DAVContext [] req B.empty B.empty [] Nothing mgr Nothing "hDav-using application"
- liftIO $ closeManager mgr
- return r
+ return $ DAVContext [] req B.empty B.empty [] Nothing mgr Nothing "hDav-using application"
+
+closeDAVContext :: MonadIO m => DAVContext -> m ()
+closeDAVContext ctx = liftIO $ closeManager (ctx ^. httpManager)
+
+withDAVContext :: (MonadIO m, MonadBaseControl IO m) => DAVURL -> (DAVContext -> m a) -> m a
+withDAVContext u = bracket (mkDAVContext u) closeDAVContext
+
+runDAVContext :: MonadIO m => DAVContext -> DAVT m a -> m (Either String a, DAVContext)
+runDAVContext ctx f = (runStateT . runEitherT . runDAVT) f ctx
choke :: IO (Either String a) -> IO a
choke f = do
--
2.1.0.rc1
From aa8fea0da0388fe8e76798587a915a75f731f548 Mon Sep 17 00:00:00 2001
From: Joey Hess <[email protected]>
Date: Wed, 6 Aug 2014 18:18:02 -0400
Subject: [PATCH 2/2] add inDAVLocation and getDAVLocation
inDAVLocation is useful for composing DAV monad actions that operate on
different locations within the same DAV repository.
getDAVLocation can be useful when writing code that might need to eg,
create the parent collection that will hold the current location.
Needed to pull in utf-8 string in order to convert from Request paths
to strings.
---
DAV.cabal | 4 +++-
Network/Protocol/HTTP/DAV.hs | 41 ++++++++++++++++++++++++++++++++++++++++-
debian/control | 3 +++
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/DAV.cabal b/DAV.cabal
index bf54f44..85eb50e 100644
--- a/DAV.cabal
+++ b/DAV.cabal
@@ -1,5 +1,5 @@
name: DAV
-version: 0.6.2
+version: 0.7.0
synopsis: RFC 4918 WebDAV support
description:
This is a library for the Web Distributed Authoring and Versioning
@@ -40,6 +40,7 @@ library
, mtl >= 2.1
, transformers >= 0.3
, transformers-base
+ , utf8-string
, xml-conduit >= 1.0 && < 1.3
, xml-hamlet >= 0.4 && <= 0.5
executable hdav
@@ -63,6 +64,7 @@ executable hdav
, optparse-applicative >= 0.5.0
, transformers >= 0.3
, transformers-base
+ , utf8-string
, xml-conduit >= 1.0 && < 1.3
, xml-hamlet >= 0.4 && <= 0.5
diff --git a/Network/Protocol/HTTP/DAV.hs b/Network/Protocol/HTTP/DAV.hs
index 06d1ee9..ca8fe59 100644
--- a/Network/Protocol/HTTP/DAV.hs
+++ b/Network/Protocol/HTTP/DAV.hs
@@ -51,6 +51,8 @@ module Network.Protocol.HTTP.DAV (
, putContentM'
, withLockIfPossible
, withLockIfPossibleForDelete
+ , inDAVLocation
+ , getDAVLocation
, module Network.Protocol.HTTP.DAV.TH
) where
@@ -72,11 +74,12 @@ import Control.Monad.Trans.Control (MonadBaseControl(..))
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC8
import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.UTF8 as UTF8B
import qualified Data.Map as Map
import Data.Maybe (catMaybes, fromMaybe)
-import Network.HTTP.Client (RequestBody(..), httpLbs, parseUrl, applyBasicAuth, Request(..), Response(..), newManager, closeManager, HttpException(..), BodyReader, withResponse)
+import Network.HTTP.Client (RequestBody(..), httpLbs, parseUrl, applyBasicAuth, Request(..), Response(..), newManager, closeManager, HttpException(..), BodyReader, withResponse, path)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Network.HTTP.Types (hContentType, Method, Status, RequestHeaders, unauthorized401, conflict409)
@@ -403,3 +406,39 @@ calendarquery = XML.Document (XML.Prologue [] Nothing []) root []
<C:filter>
<C:comp-filter name="VCALENDAR">
|]
+
+-- | Normally, DAVT actions act on the url that is provided to eg, evalDAVT.
+-- Sometimes, it's useful to adjust the url that is acted on, while
+-- remaining in the same DAV session.
+--
+-- inLocation temporarily adjusts the url's path, while performing a
+-- DAVT action.
+--
+-- For example:
+--
+-- > import System.FilePath.Posix -- posix for url path manipulation
+-- >
+-- > mkColRecursive d = do
+-- > let parent = takeDirectory d
+-- > when (parent /= d) $
+-- > mkColRecursive parent
+-- > inDavLocation (</> d) mkCol
+--
+-- Note that operations that modify the DAVContext
+-- (such as setCreds and setCreds) can be run inside davLocation,
+-- but will not have any effect on the calling DAVContext.
+inDAVLocation :: MonadIO m => (String -> String) -> DAVT m a -> DAVT m a
+inDAVLocation f a = do
+ ctx <- get
+ let r = ctx ^. baseRequest
+ let r' = r { path = adjustpath r }
+ let ctx' = ctx { _baseRequest = r' }
+ lift $ either error return =<< (evalStateT . runEitherT . runDAVT) a ctx'
+ where
+ adjustpath = UTF8B.fromString . f . UTF8B.toString . path
+
+-- | Gets the path of the url that DAVT actions will act on.
+getDAVLocation :: Monad m => DAVT m String
+getDAVLocation = do
+ ctx <- get
+ return (UTF8B.toString $ path $ ctx ^. baseRequest)
diff --git a/debian/control b/debian/control
index e0f3ed3..d538a9b 100644
--- a/debian/control
+++ b/debian/control
@@ -37,6 +37,8 @@ Build-Depends: debhelper (>= 9)
, libghc-transformers-prof
, libghc-transformers-base-dev
, libghc-transformers-base-prof
+ , libghc-utf8-string-dev
+ , libghc-utf8-string-prof
, libghc-xml-conduit-dev (>= 1.0)
, libghc-xml-conduit-dev (<< 1.3)
, libghc-xml-conduit-prof
@@ -58,6 +60,7 @@ Build-Depends-Indep: ghc-doc
, libghc-optparse-applicative-doc
, libghc-transformers-doc
, libghc-transformers-base-doc
+ , libghc-utf8-string-doc
, libghc-xml-conduit-doc
, libghc-xml-hamlet-doc
Standards-Version: 3.9.5
--
2.1.0.rc1
signature.asc
Description: Digital signature
--- End Message ---