summaryrefslogtreecommitdiff
path: root/Annex
diff options
context:
space:
mode:
Diffstat (limited to 'Annex')
-rw-r--r--Annex/AdjustedBranch.hs6
-rw-r--r--Annex/Branch.hs6
-rw-r--r--Annex/CatFile.hs1
-rw-r--r--Annex/ChangedRefs.hs108
-rw-r--r--Annex/Content.hs4
-rw-r--r--Annex/Content/Direct.hs6
-rw-r--r--Annex/DirHashes.hs1
-rw-r--r--Annex/FileMatcher.hs2
-rw-r--r--Annex/Init.hs2
-rw-r--r--Annex/Journal.hs3
-rw-r--r--Annex/Link.hs2
-rw-r--r--Annex/Locations.hs5
-rw-r--r--Annex/Notification.hs6
-rw-r--r--Annex/SpecialRemote.hs3
-rw-r--r--Annex/Ssh.hs40
-rw-r--r--Annex/Transfer.hs5
-rw-r--r--Annex/VariantFile.hs1
-rw-r--r--Annex/View.hs4
18 files changed, 146 insertions, 59 deletions
diff --git a/Annex/AdjustedBranch.hs b/Annex/AdjustedBranch.hs
index 4caf637c7..72c07a5bc 100644
--- a/Annex/AdjustedBranch.hs
+++ b/Annex/AdjustedBranch.hs
@@ -596,7 +596,7 @@ checkAdjustedClone = ifM isBareRepo
aps <- fmap commitParent <$> findAdjustingCommit (AdjBranch currbranch)
case aps of
Just [p] -> setBasisBranch basis p
- _ -> error $ "Unable to clean up from clone of adjusted branch; perhaps you should check out " ++ Git.Ref.describe origbranch
+ _ -> giveup $ "Unable to clean up from clone of adjusted branch; perhaps you should check out " ++ Git.Ref.describe origbranch
ifM versionSupportsUnlockedPointers
( return InAdjustedClone
, return NeedUpgradeForAdjustedClone
@@ -610,6 +610,6 @@ isGitVersionSupported = not <$> Git.Version.older "2.2.0"
checkVersionSupported :: Annex ()
checkVersionSupported = do
unlessM versionSupportsAdjustedBranch $
- error "Adjusted branches are only supported in v6 or newer repositories."
+ giveup "Adjusted branches are only supported in v6 or newer repositories."
unlessM (liftIO isGitVersionSupported) $
- error "Your version of git is too old; upgrade it to 2.2.0 or newer to use adjusted branches."
+ giveup "Your version of git is too old; upgrade it to 2.2.0 or newer to use adjusted branches."
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index a426c76d8..c90958ab0 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -61,6 +61,7 @@ import qualified Annex.Queue
import Annex.Branch.Transitions
import qualified Annex
import Annex.Hook
+import Utility.FileSystemEncoding
{- Name of the branch that is used to store git-annex's information. -}
name :: Git.Ref
@@ -225,7 +226,7 @@ getHistorical date file =
-- This check avoids some ugly error messages when the reflog
-- is empty.
ifM (null <$> inRepo (Git.RefLog.get' [Param (fromRef fullname), Param "-n1"]))
- ( error ("No reflog for " ++ fromRef fullname)
+ ( giveup ("No reflog for " ++ fromRef fullname)
, getRef (Git.Ref.dateRef fullname date) file
)
@@ -436,7 +437,6 @@ stageJournal jl = withIndex $ do
g <- gitRepo
let dir = gitAnnexJournalDir g
(jlogf, jlogh) <- openjlog
- liftIO $ fileEncoding jlogh
h <- hashObjectHandle
withJournalHandle $ \jh ->
Git.UpdateIndex.streamUpdateIndex g
@@ -574,7 +574,7 @@ checkBranchDifferences ref = do
<$> catFile ref differenceLog
mydiffs <- annexDifferences <$> Annex.getGitConfig
when (theirdiffs /= mydiffs) $
- error "Remote repository is tuned in incompatable way; cannot be merged with local repository."
+ giveup "Remote repository is tuned in incompatable way; cannot be merged with local repository."
ignoreRefs :: [Git.Sha] -> Annex ()
ignoreRefs rs = do
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
index b1d8fba28..25952dfec 100644
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -33,6 +33,7 @@ import Git.FilePath
import Git.Index
import qualified Git.Ref
import Annex.Link
+import Utility.FileSystemEncoding
catFile :: Git.Branch -> FilePath -> Annex L.ByteString
catFile branch file = do
diff --git a/Annex/ChangedRefs.hs b/Annex/ChangedRefs.hs
new file mode 100644
index 000000000..1f2372c04
--- /dev/null
+++ b/Annex/ChangedRefs.hs
@@ -0,0 +1,108 @@
+{- Waiting for changed git refs
+ -
+ - Copyright 2014-216 Joey Hess <id@joeyh.name>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Annex.ChangedRefs
+ ( ChangedRefs(..)
+ , ChangedRefsHandle
+ , waitChangedRefs
+ , drainChangedRefs
+ , stopWatchingChangedRefs
+ , watchChangedRefs
+ ) where
+
+import Annex.Common
+import Utility.DirWatcher
+import Utility.DirWatcher.Types
+import qualified Git
+import Git.Sha
+import qualified Utility.SimpleProtocol as Proto
+
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Concurrent.STM.TBMChan
+
+newtype ChangedRefs = ChangedRefs [Git.Ref]
+ deriving (Show)
+
+instance Proto.Serializable ChangedRefs where
+ serialize (ChangedRefs l) = unwords $ map Git.fromRef l
+ deserialize = Just . ChangedRefs . map Git.Ref . words
+
+data ChangedRefsHandle = ChangedRefsHandle DirWatcherHandle (TBMChan Git.Sha)
+
+-- | Wait for one or more git refs to change.
+--
+-- When possible, coalesce ref writes that occur closely together
+-- in time. Delay up to 0.05 seconds to get more ref writes.
+waitChangedRefs :: ChangedRefsHandle -> IO ChangedRefs
+waitChangedRefs (ChangedRefsHandle _ chan) = do
+ v <- atomically $ readTBMChan chan
+ case v of
+ Nothing -> return $ ChangedRefs []
+ Just r -> do
+ threadDelay 50000
+ rs <- atomically $ loop []
+ return $ ChangedRefs (r:rs)
+ where
+ loop rs = do
+ v <- tryReadTBMChan chan
+ case v of
+ Just (Just r) -> loop (r:rs)
+ _ -> return rs
+
+-- | Remove any changes that might be buffered in the channel,
+-- without waiting for any new changes.
+drainChangedRefs :: ChangedRefsHandle -> IO ()
+drainChangedRefs (ChangedRefsHandle _ chan) = atomically go
+ where
+ go = do
+ v <- tryReadTBMChan chan
+ case v of
+ Just (Just _) -> go
+ _ -> return ()
+
+stopWatchingChangedRefs :: ChangedRefsHandle -> IO ()
+stopWatchingChangedRefs h@(ChangedRefsHandle wh chan) = do
+ stopWatchDir wh
+ atomically $ closeTBMChan chan
+ drainChangedRefs h
+
+watchChangedRefs :: Annex (Maybe ChangedRefsHandle)
+watchChangedRefs = do
+ -- This channel is used to accumulate notifications,
+ -- because the DirWatcher might have multiple threads that find
+ -- changes at the same time. It is bounded to allow a watcher
+ -- to be started once and reused, without too many changes being
+ -- buffered in memory.
+ chan <- liftIO $ newTBMChanIO 100
+
+ g <- gitRepo
+ let refdir = Git.localGitDir g </> "refs"
+ liftIO $ createDirectoryIfMissing True refdir
+
+ let notifyhook = Just $ notifyHook chan
+ let hooks = mkWatchHooks
+ { addHook = notifyhook
+ , modifyHook = notifyhook
+ }
+
+ if canWatch
+ then do
+ h <- liftIO $ watchDir refdir (const False) True hooks id
+ return $ Just $ ChangedRefsHandle h chan
+ else return Nothing
+
+notifyHook :: TBMChan Git.Sha -> FilePath -> Maybe FileStatus -> IO ()
+notifyHook chan reffile _
+ | ".lock" `isSuffixOf` reffile = noop
+ | otherwise = void $ do
+ sha <- catchDefaultIO Nothing $
+ extractSha <$> readFile reffile
+ -- When the channel is full, there is probably no reader
+ -- running, or ref changes have been occuring very fast,
+ -- so it's ok to not write the change to it.
+ maybe noop (void . atomically . tryWriteTBMChan chan) sha
diff --git a/Annex/Content.hs b/Annex/Content.hs
index cb96a0068..e879e4eeb 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -268,8 +268,8 @@ lockContentUsing locker key a = do
(unlock lockfile)
(const a)
where
- alreadylocked = error "content is locked"
- failedtolock e = error $ "failed to lock content: " ++ show e
+ alreadylocked = giveup "content is locked"
+ failedtolock e = giveup $ "failed to lock content: " ++ show e
lock contentfile lockfile =
(maybe alreadylocked return
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
index 2007360e3..734a0c1b9 100644
--- a/Annex/Content/Direct.hs
+++ b/Annex/Content/Direct.hs
@@ -52,8 +52,7 @@ associatedFiles key = do
associatedFilesRelative :: Key -> Annex [FilePath]
associatedFilesRelative key = do
mapping <- calcRepo $ gitAnnexMapping key
- liftIO $ catchDefaultIO [] $ withFile mapping ReadMode $ \h -> do
- fileEncoding h
+ liftIO $ catchDefaultIO [] $ withFile mapping ReadMode $ \h ->
-- Read strictly to ensure the file is closed
-- before changeAssociatedFiles tries to write to it.
-- (Especially needed on Windows.)
@@ -68,8 +67,7 @@ changeAssociatedFiles key transform = do
let files' = transform files
when (files /= files') $
modifyContent mapping $
- liftIO $ viaTmp writeFileAnyEncoding mapping $
- unlines files'
+ liftIO $ viaTmp writeFile mapping $ unlines files'
top <- fromRepo Git.repoPath
return $ map (top </>) files'
diff --git a/Annex/DirHashes.hs b/Annex/DirHashes.hs
index 004536ca7..ed20cfb8a 100644
--- a/Annex/DirHashes.hs
+++ b/Annex/DirHashes.hs
@@ -26,6 +26,7 @@ import Common
import Types.Key
import Types.GitConfig
import Types.Difference
+import Utility.FileSystemEncoding
type Hasher = Key -> FilePath
diff --git a/Annex/FileMatcher.hs b/Annex/FileMatcher.hs
index fa46e64b1..654c5a960 100644
--- a/Annex/FileMatcher.hs
+++ b/Annex/FileMatcher.hs
@@ -165,7 +165,7 @@ largeFilesMatcher = go =<< annexLargeFiles <$> Annex.getGitConfig
mkmatcher expr = do
parser <- mkLargeFilesParser
either badexpr return $ parsedToMatcher $ parser expr
- badexpr e = error $ "bad annex.largefiles configuration: " ++ e
+ badexpr e = giveup $ "bad annex.largefiles configuration: " ++ e
simply :: MatchFiles Annex -> ParseResult
simply = Right . Operation
diff --git a/Annex/Init.hs b/Annex/Init.hs
index 5aff4cf39..8a208fe2b 100644
--- a/Annex/Init.hs
+++ b/Annex/Init.hs
@@ -129,7 +129,7 @@ ensureInitialized = getVersion >>= maybe needsinit checkUpgrade
where
needsinit = ifM Annex.Branch.hasSibling
( initialize Nothing Nothing
- , error "First run: git-annex init"
+ , giveup "First run: git-annex init"
)
{- Checks if a repository is initialized. Does not check version for ugrade. -}
diff --git a/Annex/Journal.hs b/Annex/Journal.hs
index e4faa4865..184bb0ab0 100644
--- a/Annex/Journal.hs
+++ b/Annex/Journal.hs
@@ -37,7 +37,6 @@ setJournalFile _jl file content = do
let tmpfile = tmp </> takeFileName jfile
liftIO $ do
withFile tmpfile WriteMode $ \h -> do
- fileEncoding h
#ifdef mingw32_HOST_OS
hSetNewlineMode h noNewlineTranslation
#endif
@@ -53,7 +52,7 @@ getJournalFile _jl = getJournalFileStale
- changes. -}
getJournalFileStale :: FilePath -> Annex (Maybe String)
getJournalFileStale file = inRepo $ \g -> catchMaybeIO $
- readFileStrictAnyEncoding $ journalFile file g
+ readFileStrict $ journalFile file g
{- List of files that have updated content in the journal. -}
getJournalledFiles :: JournalLocked -> Annex [FilePath]
diff --git a/Annex/Link.hs b/Annex/Link.hs
index 90312a04a..fcc300bee 100644
--- a/Annex/Link.hs
+++ b/Annex/Link.hs
@@ -24,6 +24,7 @@ import Git.Types
import Git.FilePath
import Annex.HashObject
import Utility.FileMode
+import Utility.FileSystemEncoding
import qualified Data.ByteString.Lazy as L
@@ -63,7 +64,6 @@ getAnnexLinkTarget' file coresymlinks = if coresymlinks
Nothing -> fallback
probefilecontent f = withFile f ReadMode $ \h -> do
- fileEncoding h
-- The first 8k is more than enough to read; link
-- files are small.
s <- take 8192 <$> hGetContents h
diff --git a/Annex/Locations.hs b/Annex/Locations.hs
index 9f829fda1..a6af4d417 100644
--- a/Annex/Locations.hs
+++ b/Annex/Locations.hs
@@ -63,7 +63,6 @@ module Annex.Locations (
gitAnnexUrlFile,
gitAnnexTmpCfgFile,
gitAnnexSshDir,
- gitAnnexSshConfig,
gitAnnexRemotesDir,
gitAnnexAssistantDefaultDir,
HashLevels(..),
@@ -403,10 +402,6 @@ gitAnnexTmpCfgFile r = gitAnnexDir r </> "config.tmp"
gitAnnexSshDir :: Git.Repo -> FilePath
gitAnnexSshDir r = addTrailingPathSeparator $ gitAnnexDir r </> "ssh"
-{- .git/annex/ssh.config is used to configure ssh. -}
-gitAnnexSshConfig :: Git.Repo -> FilePath
-gitAnnexSshConfig r = gitAnnexDir r </> "ssh.config"
-
{- .git/annex/remotes/ is used for remote-specific state. -}
gitAnnexRemotesDir :: Git.Repo -> FilePath
gitAnnexRemotesDir r = addTrailingPathSeparator $ gitAnnexDir r </> "remotes"
diff --git a/Annex/Notification.hs b/Annex/Notification.hs
index 4f492878b..e61b362ad 100644
--- a/Annex/Notification.hs
+++ b/Annex/Notification.hs
@@ -7,7 +7,7 @@
{-# LANGUAGE CPP #-}
-module Annex.Notification (NotifyWitness, notifyTransfer, notifyDrop) where
+module Annex.Notification (NotifyWitness, noNotification, notifyTransfer, notifyDrop) where
import Annex.Common
import Types.Transfer
@@ -21,6 +21,10 @@ import qualified DBus.Client
-- Witness that notification has happened.
data NotifyWitness = NotifyWitness
+-- Only use when no notification should be done.
+noNotification :: NotifyWitness
+noNotification = NotifyWitness
+
{- Wrap around an action that performs a transfer, which may run multiple
- attempts. Displays notification when supported and when the user asked
- for it. -}
diff --git a/Annex/SpecialRemote.hs b/Annex/SpecialRemote.hs
index 02799db85..0fd24f023 100644
--- a/Annex/SpecialRemote.hs
+++ b/Annex/SpecialRemote.hs
@@ -13,12 +13,11 @@ import Types.Remote (RemoteConfig, RemoteConfigKey, typename, setup)
import Logs.Remote
import Logs.Trust
import qualified Git.Config
+import Git.Types (RemoteName)
import qualified Data.Map as M
import Data.Ord
-type RemoteName = String
-
{- See if there's an existing special remote with this name.
-
- Prefer remotes that are not dead when a name appears multiple times. -}
diff --git a/Annex/Ssh.hs b/Annex/Ssh.hs
index 4377de4c5..512f0375c 100644
--- a/Annex/Ssh.hs
+++ b/Annex/Ssh.hs
@@ -33,7 +33,7 @@ import qualified Git.Url
import Config
import Annex.Path
import Utility.Env
-import Utility.Tmp
+import Utility.FileSystemEncoding
import Types.CleanupActions
import Git.Env
#ifndef mingw32_HOST_OS
@@ -50,37 +50,13 @@ sshOptions (host, port) gc opts = go =<< sshCachingInfo (host, port)
go (Just socketfile, params) = do
prepSocket socketfile
ret params
- ret ps = do
- overideconfigfile <- fromRepo gitAnnexSshConfig
- -- We assume that the file content does not change.
- -- If it did, a more expensive test would be needed.
- liftIO $ unlessM (doesFileExist overideconfigfile) $
- viaTmp writeFile overideconfigfile $ unlines
- -- Make old version of ssh that does
- -- not know about Include ignore those
- -- entries.
- [ "IgnoreUnknown Include"
- -- ssh expands "~"
- , "Include ~/.ssh/config"
- -- ssh will silently skip the file
- -- if it does not exist
- , "Include /etc/ssh/ssh_config"
- -- Everything below this point is only
- -- used if there's no setting for it in
- -- the above files.
- --
- -- Make sure that ssh detects stalled
- -- connections.
- , "ServerAliveInterval 60"
- ]
- return $ concat
- [ ps
- , [Param "-F", File overideconfigfile]
- , map Param (remoteAnnexSshOptions gc)
- , opts
- , portParams port
- , [Param "-T"]
- ]
+ ret ps = return $ concat
+ [ ps
+ , map Param (remoteAnnexSshOptions gc)
+ , opts
+ , portParams port
+ , [Param "-T"]
+ ]
{- Returns a filename to use for a ssh connection caching socket, and
- parameters to enable ssh connection caching. -}
diff --git a/Annex/Transfer.hs b/Annex/Transfer.hs
index 323600e96..b33dace4a 100644
--- a/Annex/Transfer.hs
+++ b/Annex/Transfer.hs
@@ -45,6 +45,11 @@ instance Observable (Bool, Verification) where
observeBool = fst
observeFailure = (False, UnVerified)
+instance Observable (Either e Bool) where
+ observeBool (Left _) = False
+ observeBool (Right b) = b
+ observeFailure = Right False
+
upload :: Observable v => UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex v) -> NotifyWitness -> Annex v
upload u key f d a _witness = guardHaveUUID u $
runTransfer (Transfer Upload u key) f d a
diff --git a/Annex/VariantFile.hs b/Annex/VariantFile.hs
index 9bf027b5c..17658a9c6 100644
--- a/Annex/VariantFile.hs
+++ b/Annex/VariantFile.hs
@@ -8,6 +8,7 @@
module Annex.VariantFile where
import Annex.Common
+import Utility.FileSystemEncoding
import Data.Hash.MD5
diff --git a/Annex/View.hs b/Annex/View.hs
index 7d2b43e60..d865c8f78 100644
--- a/Annex/View.hs
+++ b/Annex/View.hs
@@ -110,7 +110,7 @@ refineView origview = checksize . calc Unchanged origview
in (view', Narrowing)
checksize r@(v, _)
- | viewTooLarge v = error $ "View is too large (" ++ show (visibleViewSize v) ++ " levels of subdirectories)"
+ | viewTooLarge v = giveup $ "View is too large (" ++ show (visibleViewSize v) ++ " levels of subdirectories)"
| otherwise = r
updateViewComponent :: ViewComponent -> MetaField -> ViewFilter -> Writer [ViewChange] ViewComponent
@@ -424,4 +424,4 @@ genViewBranch view = withViewIndex $ do
return branch
withCurrentView :: (View -> Annex a) -> Annex a
-withCurrentView a = maybe (error "Not in a view.") a =<< currentView
+withCurrentView a = maybe (giveup "Not in a view.") a =<< currentView