Merge branch 'master' into ghc7.4

Conflicts:
	Utility/Misc.hs
This commit is contained in:
Joey Hess 2012-02-03 16:48:40 -04:00
commit 44b115e0b1
16 changed files with 78 additions and 100 deletions

View file

@ -25,7 +25,6 @@ module Annex.Content (
preseedTmp, preseedTmp,
) where ) where
import System.IO.Error (try)
import Control.Exception (bracket_) import Control.Exception (bracket_)
import System.Posix.Types import System.Posix.Types
@ -79,7 +78,7 @@ lockContent key a = do
where where
lock Nothing = return Nothing lock Nothing = return Nothing
lock (Just l) = do lock (Just l) = do
v <- try $ setLock l (WriteLock, AbsoluteSeek, 0, 0) v <- tryIO $ setLock l (WriteLock, AbsoluteSeek, 0, 0)
case v of case v of
Left _ -> error "content is locked" Left _ -> error "content is locked"
Right _ -> return $ Just l Right _ -> return $ Just l

View file

@ -91,4 +91,4 @@ lockJournal a = do
{- Runs an action, catching failure and running something to fix it up, and {- Runs an action, catching failure and running something to fix it up, and
- retrying if necessary. -} - retrying if necessary. -}
doRedo :: IO a -> IO b -> IO a doRedo :: IO a -> IO b -> IO a
doRedo a b = catch a $ const $ b >> a doRedo a b = catchIO a $ const $ b >> a

View file

@ -11,7 +11,6 @@ module Annex.Ssh (
) where ) where
import qualified Data.Map as M import qualified Data.Map as M
import System.IO.Error (try)
import Common.Annex import Common.Annex
import Annex.LockPool import Annex.LockPool
@ -72,7 +71,8 @@ sshCleanup = do
let lockfile = socket2lock socketfile let lockfile = socket2lock socketfile
unlockFile lockfile unlockFile lockfile
fd <- liftIO $ openFd lockfile ReadWrite (Just stdFileMode) defaultFileFlags fd <- liftIO $ openFd lockfile ReadWrite (Just stdFileMode) defaultFileFlags
v <- liftIO $ try $ setLock fd (WriteLock, AbsoluteSeek, 0, 0) v <- liftIO $ tryIO $
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
case v of case v of
Left _ -> return () Left _ -> return ()
Right _ -> stopssh socketfile Right _ -> stopssh socketfile

View file

@ -16,7 +16,6 @@ module Backend (
maybeLookupBackendName maybeLookupBackendName
) where ) where
import System.IO.Error (try)
import System.Posix.Files import System.Posix.Files
import Common.Annex import Common.Annex
@ -77,7 +76,7 @@ genKey' (b:bs) file = do
- by examining what the file symlinks to. -} - by examining what the file symlinks to. -}
lookupFile :: FilePath -> Annex (Maybe (Key, Backend)) lookupFile :: FilePath -> Annex (Maybe (Key, Backend))
lookupFile file = do lookupFile file = do
tl <- liftIO $ try getsymlink tl <- liftIO $ tryIO getsymlink
case tl of case tl of
Left _ -> return Nothing Left _ -> return Nothing
Right l -> makekey l Right l -> makekey l

View file

@ -11,7 +11,6 @@ module CmdLine (
shutdown shutdown
) where ) where
import qualified System.IO.Error as IO
import qualified Control.Exception as E import qualified Control.Exception as E
import Control.Exception (throw) import Control.Exception (throw)
import System.Console.GetOpt import System.Console.GetOpt
@ -74,7 +73,7 @@ tryRun' errnum _ cmd []
| otherwise = return () | otherwise = return ()
tryRun' errnum state cmd (a:as) = run >>= handle tryRun' errnum state cmd (a:as) = run >>= handle
where where
run = IO.try $ Annex.run state $ do run = tryIO $ Annex.run state $ do
Annex.Queue.flushWhenFull Annex.Queue.flushWhenFull
a a
handle (Left err) = showerr err >> cont False state handle (Left err) = showerr err >> cont False state

View file

@ -81,7 +81,7 @@ performRemote key file backend numcopies remote = do
t <- fromRepo gitAnnexTmpDir t <- fromRepo gitAnnexTmpDir
let tmp = t </> "fsck" ++ show pid ++ "." ++ keyFile key let tmp = t </> "fsck" ++ show pid ++ "." ++ keyFile key
liftIO $ createDirectoryIfMissing True t liftIO $ createDirectoryIfMissing True t
let cleanup = liftIO $ catch (removeFile tmp) (const $ return ()) let cleanup = liftIO $ catchIO (removeFile tmp) (const $ return ())
cleanup cleanup
cleanup `after` a tmp cleanup `after` a tmp
getfile tmp = do getfile tmp = do

View file

@ -21,6 +21,7 @@ import System.Posix.Process as X hiding (executeFile)
import System.Exit as X import System.Exit as X
import Utility.Misc as X import Utility.Misc as X
import Utility.Exception as X
import Utility.SafeCommand as X import Utility.SafeCommand as X
import Utility.Path as X import Utility.Path as X
import Utility.Directory as X import Utility.Directory as X

View file

@ -8,7 +8,6 @@
module Remote.Bup (remote) where module Remote.Bup (remote) where
import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.ByteString.Lazy.Char8 as L
import System.IO.Error
import qualified Data.Map as M import qualified Data.Map as M
import System.Process import System.Process
@ -200,7 +199,7 @@ getBupUUID :: Git.Repo -> UUID -> Annex (UUID, Git.Repo)
getBupUUID r u getBupUUID r u
| Git.repoIsUrl r = return (u, r) | Git.repoIsUrl r = return (u, r)
| otherwise = liftIO $ do | otherwise = liftIO $ do
ret <- try $ Git.Config.read r ret <- tryIO $ Git.Config.read r
case ret of case ret of
Right r' -> return (toUUID $ Git.Config.get "annex.uuid" "" r', r') Right r' -> return (toUUID $ Git.Config.get "annex.uuid" "" r', r')
Left _ -> return (NoUUID, r) Left _ -> return (NoUUID, r)

View file

@ -7,8 +7,6 @@
module Upgrade.V0 where module Upgrade.V0 where
import System.IO.Error (try)
import Common.Annex import Common.Annex
import Annex.Content import Annex.Content
import qualified Upgrade.V1 import qualified Upgrade.V1
@ -47,7 +45,7 @@ getKeysPresent0 dir = do
return $ map fileKey0 files return $ map fileKey0 files
where where
present d = do present d = do
result <- try $ result <- tryIO $
getFileStatus $ dir ++ "/" ++ takeFileName d getFileStatus $ dir ++ "/" ++ takeFileName d
case result of case result of
Right s -> return $ isRegularFile s Right s -> return $ isRegularFile s

View file

@ -7,7 +7,6 @@
module Upgrade.V1 where module Upgrade.V1 where
import System.IO.Error (try)
import System.Posix.Types import System.Posix.Types
import Data.Char import Data.Char
@ -183,7 +182,7 @@ readLog1 file = catchDefaultIO (parseLog <$> readFileStrict file) []
lookupFile1 :: FilePath -> Annex (Maybe (Key, Backend)) lookupFile1 :: FilePath -> Annex (Maybe (Key, Backend))
lookupFile1 file = do lookupFile1 file = do
tl <- liftIO $ try getsymlink tl <- liftIO $ tryIO getsymlink
case tl of case tl of
Left _ -> return Nothing Left _ -> return Nothing
Right l -> makekey l Right l -> makekey l
@ -216,7 +215,7 @@ getKeyFilesPresent1' dir = do
liftIO $ filterM present files liftIO $ filterM present files
where where
present f = do present f = do
result <- try $ getFileStatus f result <- tryIO $ getFileStatus f
case result of case result of
Right s -> return $ isRegularFile s Right s -> return $ isRegularFile s
Left _ -> return False Left _ -> return False

View file

@ -16,11 +16,12 @@ import Control.Monad.IfElse
import Utility.SafeCommand import Utility.SafeCommand
import Utility.TempFile import Utility.TempFile
import Utility.Exception
{- Moves one filename to another. {- Moves one filename to another.
- First tries a rename, but falls back to moving across devices if needed. -} - First tries a rename, but falls back to moving across devices if needed. -}
moveFile :: FilePath -> FilePath -> IO () moveFile :: FilePath -> FilePath -> IO ()
moveFile src dest = try (rename src dest) >>= onrename moveFile src dest = tryIO (rename src dest) >>= onrename
where where
onrename (Right _) = return () onrename (Right _) = return ()
onrename (Left e) onrename (Left e)
@ -40,11 +41,10 @@ moveFile src dest = try (rename src dest) >>= onrename
Param src, Param tmp] Param src, Param tmp]
unless ok $ do unless ok $ do
-- delete any partial -- delete any partial
_ <- try $ _ <- tryIO $ removeFile tmp
removeFile tmp
rethrow rethrow
isdir f = do isdir f = do
r <- try (getFileStatus f) r <- tryIO $ getFileStatus f
case r of case r of
(Left _) -> return False (Left _) -> return False
(Right s) -> return $ isDirectory s (Right s) -> return $ isDirectory s

39
Utility/Exception.hs Normal file
View file

@ -0,0 +1,39 @@
{- Simple IO exception handling
-
- Copyright 2011-2012 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Utility.Exception where
import Prelude hiding (catch)
import Control.Exception
import Control.Applicative
{- Catches IO errors and returns a Bool -}
catchBoolIO :: IO Bool -> IO Bool
catchBoolIO a = catchDefaultIO a False
{- Catches IO errors and returns a Maybe -}
catchMaybeIO :: IO a -> IO (Maybe a)
catchMaybeIO a = catchDefaultIO (Just <$> a) Nothing
{- Catches IO errors and returns a default value. -}
catchDefaultIO :: IO a -> a -> IO a
catchDefaultIO a def = catchIO a (const $ return def)
{- Catches IO errors and returns the error message. -}
catchMsgIO :: IO a -> IO (Either String a)
catchMsgIO a = dispatch <$> tryIO a
where
dispatch (Left e) = Left $ show e
dispatch (Right v) = Right v
{- catch specialized for IO errors only -}
catchIO :: IO a -> (IOException -> IO a) -> IO a
catchIO = catch
{- try specialized for IO errors only -}
tryIO :: IO a -> IO (Either IOException a)
tryIO = try

View file

@ -8,9 +8,7 @@
module Utility.Misc where module Utility.Misc where
import System.IO import System.IO
import System.IO.Error (try)
import Control.Monad import Control.Monad
import Control.Applicative
import GHC.IO.Encoding import GHC.IO.Encoding
{- Sets a Handle to use the filesystem encoding. This causes data {- Sets a Handle to use the filesystem encoding. This causes data
@ -45,22 +43,3 @@ separate c l = unbreak $ break c l
{- Breaks out the first line. -} {- Breaks out the first line. -}
firstLine :: String-> String firstLine :: String-> String
firstLine = takeWhile (/= '\n') firstLine = takeWhile (/= '\n')
{- Catches IO errors and returns a Bool -}
catchBoolIO :: IO Bool -> IO Bool
catchBoolIO a = catchDefaultIO a False
{- Catches IO errors and returns a Maybe -}
catchMaybeIO :: IO a -> IO (Maybe a)
catchMaybeIO a = catchDefaultIO (Just <$> a) Nothing
{- Catches IO errors and returns a default value. -}
catchDefaultIO :: IO a -> a -> IO a
catchDefaultIO a def = catch a (const $ return def)
{- Catches IO errors and returns the error message. -}
catchMsgIO :: IO a -> IO (Either String a)
catchMsgIO a = dispatch <$> try a
where
dispatch (Left e) = Left $ show e
dispatch (Right v) = Right v

View file

@ -12,7 +12,7 @@ import System.IO
import System.Posix.Process hiding (executeFile) import System.Posix.Process hiding (executeFile)
import System.Directory import System.Directory
import Utility.Misc import Utility.Exception
import Utility.Path import Utility.Path
{- Runs an action like writeFile, writing to a temp file first and {- Runs an action like writeFile, writing to a temp file first and

View file

@ -1,6 +1,12 @@
This bug is reopened to track some new UTF-8 filename issues caused by GHC This bug is reopened to track some new UTF-8 filename issues caused by GHC
7.4. Older versions of GHC, like the 7.0.4 in debian unstable, are not 7.4. In this version of GHC, git-annex's hack to support filenames in any
affected. See the comments for details about the new bug. --[[Joey]] encoding no longer works. Even unicode filenames fail to work when
git-annex is built with 7.4. --[[Joey]]
I now have a `ghc7.4` branch in git that seems to solve this,
for all filename encodings, and all system encodings. It will
only build with the new GHC. If you have this problem, give it a try!
--[[Joey]]
---- ----
@ -74,39 +80,3 @@ It looks like the common latin1-to-UTF8 encoding. Functionality other than otupu
> > On second thought, I switched to this. Any decoding of a filename > > On second thought, I switched to this. Any decoding of a filename
> > is going to make someone unhappy; the previous approach broke > > is going to make someone unhappy; the previous approach broke
> > non-utf8 filenames. > > non-utf8 filenames.
----
Simpler test case:
<pre>
import Codec.Binary.UTF8.String
import System.Environment
main = do
args <- getArgs
let file = decodeString $ head args
putStrLn $ "file is: " ++ file
putStr =<< readFile file
</pre>
If I pass this a filename like 'ü', it will fail, and notice
the bad encoding of the filename in the error message:
<pre>
$ echo hi > ü; runghc foo.hs ü
file is: ü
foo.hs: <20>: openFile: does not exist (No such file or directory)
</pre>
On the other hand, if I remove the decodeString, it prints the filename
wrong, while accessing it right:
<pre>
$ runghc foo.hs ü
file is: üa
hi
</pre>
The only way that seems to consistently work is to delay decoding the
filename to places where it's output. But then it's easy to miss some.

View file

@ -1,25 +1,16 @@
short answer: no Can it be built on Windows?
Long answer, quoting from a mail to someone else: short answer: not yet
Well, I can tell you that it assumes a POSIX system, both in available First, you need to get some unix utilities for windows. Git of course.
utilities and system calls, So you'd need to use cygwin or something Also rsync, and a `cp` command that understands at least `cp -p`, and
like that. (Perhaps you already are for git, I think git also assumes a `uuid`, and `xargs` and `sha1sum`. Note that some of these could be
POSIX system.) So you need a Haskell that can target that. What this replaced with haskell libraries to some degree.
page refers to as "GHC-Cygwin":
<http://www.haskell.org/ghc/docs/6.6/html/building/platforms.html>
I don't know where to get one. Did find this:
<http://copilotco.com/mail-archives/haskell-cafe.2007/msg00824.html>
(There are probably also still some places where it assumes / as a path There are probably still some places where it assumes / as a path
separator, although I fixed some. Probably almost all are fixed now.) separator, although I fixed probably almost all by now.
FWIW, git-annex works fine on OS X and other fine proprietary unixen. ;P Then windows versions of these functions could be found,
--[[Joey]]
----
Alternatively, windows versions of these functions could be found,
which are all the ones that need POSIX, I think. A fair amount of this, which are all the ones that need POSIX, I think. A fair amount of this,
the stuff to do with signals and users, could be empty stubs in windows. the stuff to do with signals and users, could be empty stubs in windows.
The file manipulation, particularly symlinks, would probably be the main The file manipulation, particularly symlinks, would probably be the main
@ -63,3 +54,8 @@ sigCHLD
sigINT sigINT
unionFileModes unionFileModes
</pre> </pre>
A good starting point is
<http://hackage.haskell.org/package/unix-compat-0.3.0.1>. However, note
that its implementations of stuff like `createSymbolicLink` are stubs.
--[[Joey]]