refactor catfile code
split into generic IO code, and a thin Annex wrapper
This commit is contained in:
parent
4f4eaf387a
commit
ad245a6375
5 changed files with 96 additions and 48 deletions
3
Annex.hs
3
Annex.hs
|
@ -24,6 +24,7 @@ import Control.Monad.IO.Control
|
||||||
import Control.Applicative hiding (empty)
|
import Control.Applicative hiding (empty)
|
||||||
|
|
||||||
import qualified Git
|
import qualified Git
|
||||||
|
import Git.CatFile
|
||||||
import Git.Queue
|
import Git.Queue
|
||||||
import Types.Backend
|
import Types.Backend
|
||||||
import qualified Types.Remote
|
import qualified Types.Remote
|
||||||
|
@ -55,6 +56,7 @@ data AnnexState = AnnexState
|
||||||
, fast :: Bool
|
, fast :: Bool
|
||||||
, auto :: Bool
|
, auto :: Bool
|
||||||
, branchstate :: BranchState
|
, branchstate :: BranchState
|
||||||
|
, catfilehandle :: Maybe CatFileHandle
|
||||||
, forcebackend :: Maybe String
|
, forcebackend :: Maybe String
|
||||||
, forcenumcopies :: Maybe Int
|
, forcenumcopies :: Maybe Int
|
||||||
, defaultkey :: Maybe String
|
, defaultkey :: Maybe String
|
||||||
|
@ -79,6 +81,7 @@ newState gitrepo = AnnexState
|
||||||
, fast = False
|
, fast = False
|
||||||
, auto = False
|
, auto = False
|
||||||
, branchstate = startBranchState
|
, branchstate = startBranchState
|
||||||
|
, catfilehandle = Nothing
|
||||||
, forcebackend = Nothing
|
, forcebackend = Nothing
|
||||||
, forcenumcopies = Nothing
|
, forcenumcopies = Nothing
|
||||||
, defaultkey = Nothing
|
, defaultkey = Nothing
|
||||||
|
|
45
Branch.hs
45
Branch.hs
|
@ -18,7 +18,7 @@ module Branch (
|
||||||
name
|
name
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad (when, unless, liftM)
|
import Control.Monad (unless, liftM)
|
||||||
import Control.Monad.State (liftIO)
|
import Control.Monad.State (liftIO)
|
||||||
import Control.Applicative ((<$>))
|
import Control.Applicative ((<$>))
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
|
@ -31,7 +31,6 @@ import System.IO
|
||||||
import System.IO.Binary
|
import System.IO.Binary
|
||||||
import System.Posix.Process
|
import System.Posix.Process
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import qualified Data.ByteString.Char8 as B
|
|
||||||
|
|
||||||
import Types.BranchState
|
import Types.BranchState
|
||||||
import qualified Git
|
import qualified Git
|
||||||
|
@ -43,6 +42,7 @@ import Utility.SafeCommand
|
||||||
import Types
|
import Types
|
||||||
import Messages
|
import Messages
|
||||||
import Locations
|
import Locations
|
||||||
|
import CatFile
|
||||||
|
|
||||||
type GitRef = String
|
type GitRef = String
|
||||||
|
|
||||||
|
@ -244,49 +244,10 @@ get file = do
|
||||||
setCache file content
|
setCache file content
|
||||||
return content
|
return content
|
||||||
Nothing -> withIndexUpdate $ do
|
Nothing -> withIndexUpdate $ do
|
||||||
content <- catFile file
|
content <- catFile fullname file
|
||||||
setCache file content
|
setCache file content
|
||||||
return content
|
return content
|
||||||
|
|
||||||
{- Uses git cat-file in batch mode to read the content of a file.
|
|
||||||
-
|
|
||||||
- Only one process is run, and it persists and is used for all accesses. -}
|
|
||||||
catFile :: FilePath -> Annex String
|
|
||||||
catFile file = do
|
|
||||||
state <- getState
|
|
||||||
maybe (startup state) ask (catFileHandles state)
|
|
||||||
where
|
|
||||||
startup state = do
|
|
||||||
g <- Annex.gitRepo
|
|
||||||
(_, from, to) <- liftIO $ hPipeBoth "git" $
|
|
||||||
toCommand $ Git.gitCommandLine g
|
|
||||||
[Param "cat-file", Param "--batch"]
|
|
||||||
setState state { catFileHandles = Just (from, to) }
|
|
||||||
ask (from, to)
|
|
||||||
ask (from, to) = liftIO $ do
|
|
||||||
let want = fullname ++ ":" ++ file
|
|
||||||
hPutStrLn to want
|
|
||||||
hFlush to
|
|
||||||
header <- hGetLine from
|
|
||||||
case words header of
|
|
||||||
[sha, blob, size]
|
|
||||||
| length sha == Git.shaSize &&
|
|
||||||
blob == "blob" -> handle from size
|
|
||||||
| otherwise -> empty
|
|
||||||
_
|
|
||||||
| header == want ++ " missing" -> empty
|
|
||||||
| otherwise -> error $ "unknown response from git cat-file " ++ header
|
|
||||||
handle from size = case reads size of
|
|
||||||
[(bytes, "")] -> readcontent from bytes
|
|
||||||
_ -> empty
|
|
||||||
readcontent from bytes = do
|
|
||||||
content <- B.hGet from bytes
|
|
||||||
c <- hGetChar from
|
|
||||||
when (c /= '\n') $
|
|
||||||
error "missing newline from git cat-file"
|
|
||||||
return $ B.unpack content
|
|
||||||
empty = return ""
|
|
||||||
|
|
||||||
{- Lists all files on the branch. There may be duplicates in the list. -}
|
{- Lists all files on the branch. There may be duplicates in the list. -}
|
||||||
files :: Annex [FilePath]
|
files :: Annex [FilePath]
|
||||||
files = withIndexUpdate $ do
|
files = withIndexUpdate $ do
|
||||||
|
|
26
CatFile.hs
Normal file
26
CatFile.hs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{- git cat-file interface, with handle automatically stored in the Annex monad
|
||||||
|
-
|
||||||
|
- Copyright 2011 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module CatFile (
|
||||||
|
catFile
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.State
|
||||||
|
|
||||||
|
import qualified Git.CatFile
|
||||||
|
import Types
|
||||||
|
import qualified Annex
|
||||||
|
|
||||||
|
catFile :: String -> FilePath -> Annex String
|
||||||
|
catFile branch file = maybe startup go =<< Annex.getState Annex.catfilehandle
|
||||||
|
where
|
||||||
|
startup = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
h <- liftIO $ Git.CatFile.catFileStart g
|
||||||
|
Annex.changeState $ \s -> s { Annex.catfilehandle = Just h }
|
||||||
|
go h
|
||||||
|
go h = liftIO $ Git.CatFile.catFile h branch file
|
63
Git/CatFile.hs
Normal file
63
Git/CatFile.hs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{- git cat-file interface
|
||||||
|
-
|
||||||
|
- Copyright 2011 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Git.CatFile (
|
||||||
|
CatFileHandle,
|
||||||
|
catFileStart,
|
||||||
|
catFileStop,
|
||||||
|
catFile
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.State
|
||||||
|
import System.Cmd.Utils
|
||||||
|
import System.IO
|
||||||
|
import qualified Data.ByteString.Char8 as B
|
||||||
|
|
||||||
|
import Git
|
||||||
|
import Utility.SafeCommand
|
||||||
|
|
||||||
|
type CatFileHandle = (PipeHandle, Handle, Handle)
|
||||||
|
|
||||||
|
{- Starts git cat-file running in batch mode in a repo and returns a handle. -}
|
||||||
|
catFileStart :: Repo -> IO CatFileHandle
|
||||||
|
catFileStart repo = hPipeBoth "git" $ toCommand $
|
||||||
|
Git.gitCommandLine repo [Param "cat-file", Param "--batch"]
|
||||||
|
|
||||||
|
{- Stops git cat-file. -}
|
||||||
|
catFileStop :: CatFileHandle -> IO ()
|
||||||
|
catFileStop (pid, from, to) = do
|
||||||
|
hClose to
|
||||||
|
hClose from
|
||||||
|
forceSuccess pid
|
||||||
|
|
||||||
|
{- Uses a running git cat-file read the content of a file from a branch.
|
||||||
|
- Files that do not exist on the branch will have "" returned. -}
|
||||||
|
catFile :: CatFileHandle -> String -> FilePath -> IO String
|
||||||
|
catFile (_, from, to) branch file = do
|
||||||
|
hPutStrLn to want
|
||||||
|
hFlush to
|
||||||
|
header <- hGetLine from
|
||||||
|
case words header of
|
||||||
|
[sha, blob, size]
|
||||||
|
| length sha == Git.shaSize &&
|
||||||
|
blob == "blob" -> handle size
|
||||||
|
| otherwise -> empty
|
||||||
|
_
|
||||||
|
| header == want ++ " missing" -> empty
|
||||||
|
| otherwise -> error $ "unknown response from git cat-file " ++ header
|
||||||
|
where
|
||||||
|
want = branch ++ ":" ++ file
|
||||||
|
handle size = case reads size of
|
||||||
|
[(bytes, "")] -> readcontent bytes
|
||||||
|
_ -> empty
|
||||||
|
readcontent bytes = do
|
||||||
|
content <- B.hGet from bytes
|
||||||
|
c <- hGetChar from
|
||||||
|
when (c /= '\n') $
|
||||||
|
error "missing newline from git cat-file"
|
||||||
|
return $ B.unpack content
|
||||||
|
empty = return ""
|
|
@ -7,18 +7,13 @@
|
||||||
|
|
||||||
module Types.BranchState where
|
module Types.BranchState where
|
||||||
|
|
||||||
import System.IO
|
|
||||||
|
|
||||||
data BranchState = BranchState {
|
data BranchState = BranchState {
|
||||||
branchUpdated :: Bool, -- has the branch been updated this run?
|
branchUpdated :: Bool, -- has the branch been updated this run?
|
||||||
|
|
||||||
-- (from, to) handles used to talk to a git-cat-file process
|
|
||||||
catFileHandles :: Maybe (Handle, Handle),
|
|
||||||
|
|
||||||
-- the content of one file is cached
|
-- the content of one file is cached
|
||||||
cachedFile :: Maybe FilePath,
|
cachedFile :: Maybe FilePath,
|
||||||
cachedContent :: String
|
cachedContent :: String
|
||||||
}
|
}
|
||||||
|
|
||||||
startBranchState :: BranchState
|
startBranchState :: BranchState
|
||||||
startBranchState = BranchState False Nothing Nothing ""
|
startBranchState = BranchState False Nothing ""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue