diff --git a/Annex.hs b/Annex.hs
--- a/Annex.hs
+++ b/Annex.hs
@@ -15,6 +15,7 @@
 	eval,
 	getState,
 	changeState,
+	withState,
 	setFlag,
 	setField,
 	setOutput,
@@ -213,6 +214,11 @@
 changeState modifier = do
 	mvar <- ask
 	liftIO $ modifyMVar_ mvar $ return . modifier
+
+withState :: (AnnexState -> (AnnexState, b)) -> Annex b
+withState modifier = do
+	mvar <- ask
+	liftIO $ modifyMVar mvar $ return . modifier
 
 {- Sets a flag to True -}
 setFlag :: String -> Annex ()
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -12,6 +12,7 @@
 	catTree,
 	catObjectDetails,
 	catFileHandle,
+	catFileStop,
 	catKey,
 	catKeyFile,
 	catKeyFileHEAD,
@@ -70,6 +71,14 @@
 			let m' = M.insert indexfile h m
 			Annex.changeState $ \s -> s { Annex.catfilehandles = m' }
 			return h
+
+{- Stops all running cat-files. Should only be run when it's known that
+ - nothing is using the handles, eg at shutdown. -}
+catFileStop :: Annex ()
+catFileStop = do
+	m <- Annex.withState $ \s ->
+		(s { Annex.catfilehandles = M.empty }, Annex.catfilehandles s)
+	liftIO $ mapM_ Git.CatFile.catFileStop (M.elems m)
 
 {- From the Sha or Ref of a symlink back to the key.
  -
diff --git a/Annex/Content.hs b/Annex/Content.hs
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -56,10 +56,7 @@
 import Annex.Link
 import Annex.Content.Direct
 import Annex.ReplaceFile
-
-#ifdef mingw32_HOST_OS
-import Utility.WinLock
-#endif
+import Utility.LockFile
 
 {- Checks if a given key's content is currently present. -}
 inAnnex :: Key -> Annex Bool
@@ -104,25 +101,21 @@
 		=<< contentLockFile key
 
 #ifndef mingw32_HOST_OS
-	checkindirect f = liftIO $ openforlock f >>= check is_missing
+	checkindirect contentfile = liftIO $ checkOr is_missing contentfile
 	{- In direct mode, the content file must exist, but
-	 - the lock file often generally won't exist unless a removal is in
-	 - process. This does not create the lock file, it only checks for
-	 - it. -}
+	 - the lock file generally won't exist unless a removal is in
+	 - process. -}
 	checkdirect contentfile lockfile = liftIO $
 		ifM (doesFileExist contentfile)
-			( openforlock lockfile >>= check is_unlocked
+			( checkOr is_unlocked lockfile
 			, return is_missing
 			)
-	openforlock f = catchMaybeIO $
-		openFd f ReadOnly Nothing defaultFileFlags
-	check _ (Just h) = do
-		v <- getLock h (ReadLock, AbsoluteSeek, 0, 0)
-		closeFd h
+	checkOr def lockfile = do
+		v <- checkLocked lockfile
 		return $ case v of
-			Just _ -> is_locked
-			Nothing -> is_unlocked
-	check def Nothing = return def
+			Nothing -> def
+			Just True -> is_locked
+			Just False -> is_unlocked
 #else
 	checkindirect f = liftIO $ ifM (doesFileExist f)
 		( do
@@ -159,14 +152,20 @@
 	, return Nothing
 	)
 
+newtype ContentLock = ContentLock Key
+
 {- Content is exclusively locked while running an action that might remove
- - it. (If the content is not present, no locking is done.) -}
-lockContent :: Key -> Annex a -> Annex a
+ - it. (If the content is not present, no locking is done.)
+ -}
+lockContent :: Key -> (ContentLock -> Annex a) -> Annex a
 lockContent key a = do
 	contentfile <- calcRepo $ gitAnnexLocation key
 	lockfile <- contentLockFile key
 	maybe noop setuplockfile lockfile
-	bracket (liftIO $ lock contentfile lockfile) (unlock lockfile) (const a)
+	bracket
+		(lock contentfile lockfile)
+		(unlock lockfile)
+		(const $ a $ ContentLock key)
   where
 	alreadylocked = error "content is locked"
 	setuplockfile lockfile = modifyContent lockfile $
@@ -176,17 +175,17 @@
 		void $ liftIO $ tryIO $
 			nukeFile lockfile
 #ifndef mingw32_HOST_OS
-	lock contentfile Nothing = opencontentforlock contentfile >>= dolock
-	lock _ (Just lockfile) = openforlock lockfile >>= dolock . Just
+	lock contentfile Nothing = liftIO $
+		opencontentforlock contentfile >>= dolock
+	lock _ (Just lockfile) = do
+		mode <- annexFileMode
+		liftIO $ createLockFile mode lockfile >>= dolock . Just
 	{- Since content files are stored with the write bit disabled, have
 	 - to fiddle with permissions to open for an exclusive lock. -}
-	opencontentforlock f = catchMaybeIO $ ifM (doesFileExist f)
-		( withModifiedFileMode f
+	opencontentforlock f = catchDefaultIO Nothing $ 
+		withModifiedFileMode f
 			(`unionFileModes` ownerWriteMode)
-			(openforlock f)
-		, openforlock f
-		)
-	openforlock f = openFd f ReadWrite Nothing defaultFileFlags
+			(openExistingLockFile f)
 	dolock Nothing = return Nothing
 	dolock (Just fd) = do
 		v <- tryIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
@@ -197,7 +196,8 @@
 		maybe noop cleanuplockfile mlockfile
 		liftIO $ maybe noop closeFd mfd
 #else
-	lock _ (Just lockfile) = maybe alreadylocked (return . Just) =<< lockExclusive lockfile
+	lock _ (Just lockfile) = liftIO $
+		maybe alreadylocked (return . Just) =<< lockExclusive lockfile
 	lock _ Nothing = return Nothing
 	unlock mlockfile mlockhandle = do
 		liftIO $ maybe noop dropLock mlockhandle
@@ -432,9 +432,10 @@
 {- Removes a key's file from .git/annex/objects/
  -
  - In direct mode, deletes the associated files or files, and replaces
- - them with symlinks. -}
-removeAnnex :: Key -> Annex ()
-removeAnnex key = withObjectLoc key remove removedirect
+ - them with symlinks.
+ -}
+removeAnnex :: ContentLock -> Annex ()
+removeAnnex (ContentLock key) = withObjectLoc key remove removedirect
   where
 	remove file = cleanObjectLoc key $ do
 		secureErase file
@@ -579,7 +580,7 @@
 		( return True
 		, do
 			s <- calcRepo $ gitAnnexLocation key
-			liftIO $ copyFileExternal s file
+			liftIO $ copyFileExternal CopyTimeStamps s file
 		)
 
 {- Blocks writing to an annexed file, and modifies file permissions to
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
--- a/Annex/Content/Direct.hs
+++ b/Annex/Content/Direct.hs
@@ -210,7 +210,7 @@
 	v <- isAnnexLink associatedfile
 	when (Just key == v) $
 		replaceFile associatedfile $
-			liftIO . void . copyFileExternal contentfile
+			liftIO . void . copyFileExternal CopyAllMetaData contentfile
 	updateInodeCache key associatedfile	
 
 {- Some filesystems get new inodes each time they are mounted.
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
--- a/Annex/Direct.hs
+++ b/Annex/Direct.hs
@@ -357,7 +357,7 @@
 				`catchIO` (\_ -> freezeContent loc)
 	fromdirect loc = do
 		replaceFile f $
-			liftIO . void . copyFileExternal loc
+			liftIO . void . copyFileExternal CopyAllMetaData loc
 		updateInodeCache k f
 
 {- Removes a direct mode file, while retaining its content in the annex
diff --git a/Annex/LockFile.hs b/Annex/LockFile.hs
--- a/Annex/LockFile.hs
+++ b/Annex/LockFile.hs
@@ -19,13 +19,10 @@
 import Types.LockPool
 import qualified Git
 import Annex.Perms
+import Utility.LockFile
 
 import qualified Data.Map as M
 
-#ifdef mingw32_HOST_OS
-import Utility.WinLock
-#endif
-
 {- Create a specified lock file, and takes a shared lock, which is retained
  - in the pool. -}
 lockFileShared :: FilePath -> Annex ()
@@ -35,9 +32,7 @@
 	go Nothing = do
 #ifndef mingw32_HOST_OS
 		mode <- annexFileMode
-		lockhandle <- liftIO $ noUmask mode $
-			openFd file ReadOnly (Just mode) defaultFileFlags
-		liftIO $ waitToSetLock lockhandle (ReadLock, AbsoluteSeek, 0, 0)
+		lockhandle <- liftIO $ noUmask mode $ lockShared (Just mode) file
 #else
 		lockhandle <- liftIO $ waitToLock $ lockShared file
 #endif
@@ -47,11 +42,7 @@
 unlockFile file = maybe noop go =<< fromLockPool file
   where
 	go lockhandle = do
-#ifndef mingw32_HOST_OS
-		liftIO $ closeFd lockhandle
-#else
 		liftIO $ dropLock lockhandle
-#endif
 		changeLockPool $ M.delete file
 
 getLockPool :: Annex LockPool
@@ -72,15 +63,10 @@
 	lockfile <- fromRepo getlockfile
 	createAnnexDirectory $ takeDirectory lockfile
 	mode <- annexFileMode
-	bracketIO (lock lockfile mode) unlock (const a)
+	bracketIO (lock mode lockfile) dropLock (const a)
   where
 #ifndef mingw32_HOST_OS
-	lock lockfile mode = do
-		l <- noUmask mode $ createFile lockfile mode
-		waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
-		return l
-	unlock = closeFd
+	lock mode = noUmask mode . lockExclusive (Just mode)
 #else
-	lock lockfile _mode = waitToLock $ lockExclusive lockfile
-	unlock = dropLock
+	lock _mode = waitToLock . lockExclusive
 #endif
diff --git a/Annex/Ssh.hs b/Annex/Ssh.hs
--- a/Annex/Ssh.hs
+++ b/Annex/Ssh.hs
@@ -35,6 +35,7 @@
 import Utility.Env
 import Types.CleanupActions
 import Annex.Index (addGitEnv)
+import Utility.LockFile
 #ifndef mingw32_HOST_OS
 import Annex.Perms
 #endif
@@ -151,14 +152,12 @@
 		let lockfile = socket2lock socketfile
 		unlockFile lockfile
 		mode <- annexFileMode
-		fd <- liftIO $ noUmask mode $
-			openFd lockfile ReadWrite (Just mode) defaultFileFlags
-		v <- liftIO $ tryIO $
-			setLock fd (WriteLock, AbsoluteSeek, 0, 0)
+		v <- liftIO $ noUmask mode $ tryLockExclusive (Just mode) lockfile
 		case v of
-			Left _ -> noop
-			Right _ -> forceStopSsh socketfile
-		liftIO $ closeFd fd
+			Nothing -> noop
+			Just lck -> do
+				forceStopSsh socketfile
+				liftIO $ dropLock lck
 #else
 		forceStopSsh socketfile
 #endif
diff --git a/Annex/Transfer.hs b/Annex/Transfer.hs
--- a/Annex/Transfer.hs
+++ b/Annex/Transfer.hs
@@ -23,7 +23,7 @@
 import Annex.Perms
 import Utility.Metered
 #ifdef mingw32_HOST_OS
-import Utility.WinLock
+import Utility.LockFile
 #endif
 
 import Control.Concurrent
@@ -81,6 +81,7 @@
 		case mfd of
 			Nothing -> return (Nothing, False)
 			Just fd -> do
+				setFdOption fd CloseOnExec True
 				locked <- catchMaybeIO $
 					setLock fd (WriteLock, AbsoluteSeek, 0, 0)
 				if isNothing locked
diff --git a/Assistant/Unused.hs b/Assistant/Unused.hs
--- a/Assistant/Unused.hs
+++ b/Assistant/Unused.hs
@@ -77,7 +77,7 @@
 	forM_ oldkeys $ \k -> do
 		debug ["removing old unused key", key2file k]
 		liftAnnex $ do
-			removeAnnex k
+			lockContent k removeAnnex
 			logStatus k InfoMissing
   where
 	boundry = durationToPOSIXTime <$> duration
diff --git a/Assistant/Upgrade.hs b/Assistant/Upgrade.hs
--- a/Assistant/Upgrade.hs
+++ b/Assistant/Upgrade.hs
@@ -96,7 +96,7 @@
 		, transferKey = k
 		}
 	cleanup = liftAnnex $ do
-		removeAnnex k
+		lockContent k removeAnnex
 		setUrlMissing k u
 		logStatus k InfoMissing
 
diff --git a/Build/Configure.hs b/Build/Configure.hs
--- a/Build/Configure.hs
+++ b/Build/Configure.hs
@@ -23,6 +23,7 @@
 	, TestCase "git version" getGitVersion
 	, testCp "cp_a" "-a"
 	, testCp "cp_p" "-p"
+	, testCp "cp_preserve_timestamps" "--preserve=timestamps"
 	, testCp "cp_reflink_auto" "--reflink=auto"
 	, TestCase "xargs -0" $ requireCmd "xargs_0" "xargs -0 </dev/null"
 	, TestCase "rsync" $ requireCmd "rsync" "rsync --version >/dev/null"
diff --git a/Build/LinuxMkLibs.hs b/Build/LinuxMkLibs.hs
--- a/Build/LinuxMkLibs.hs
+++ b/Build/LinuxMkLibs.hs
@@ -82,7 +82,7 @@
 installFile :: FilePath -> FilePath -> IO ()
 installFile top f = do
 	createDirectoryIfMissing True destdir
-	void $ copyFileExternal f destdir
+	void $ copyFileExternal CopyTimeStamps f destdir
   where
 	destdir = inTop top $ parentDir f
 
diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,19 @@
+git-annex (5.20140831) unstable; urgency=medium
+
+  * Make --help work when not in a git repository. Closes: #758592
+  * Ensure that all lock fds are close-on-exec, fixing various problems with
+    them being inherited by child processes such as git commands.
+  * When accessing a local remote, shut down git-cat-file processes
+    afterwards, to ensure that remotes on removable media can be unmounted.
+    Closes: #758630
+  * Fix handing of autocorrection when running outside a git repository.
+  * Fix stub git-annex test support when built without tasty.
+  * Do not preserve permissions and acls when copying files from
+    one local git repository to another. Timestamps are still preserved
+    as long as cp --preserve=timestamps is supported. Closes: #729757
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 31 Aug 2014 12:30:08 -0700
+
 git-annex (5.20140817) unstable; urgency=medium
 
   * New chunk= option to chunk files stored in special remotes.
diff --git a/CmdLine.hs b/CmdLine.hs
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -6,6 +6,7 @@
  -}
 
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE BangPatterns #-}
 
 module CmdLine (
 	dispatch,
@@ -25,6 +26,7 @@
 import qualified Annex
 import qualified Git
 import qualified Git.AutoCorrect
+import qualified Git.Config
 import Annex.Content
 import Annex.Environment
 import Command
@@ -34,30 +36,34 @@
 dispatch :: Bool -> CmdParams -> [Command] -> [Option] -> [(String, String)] -> String -> IO Git.Repo -> IO ()
 dispatch fuzzyok allargs allcmds commonoptions fields header getgitrepo = do
 	setupConsole
-	r <- E.try getgitrepo :: IO (Either E.SomeException Git.Repo)
-	case r of
-		Left e -> maybe (throw e) (\a -> a params) (cmdnorepo cmd)
-		Right g -> do
-			state <- Annex.new g
-			Annex.eval state $ do
-				checkEnvironment
-				checkfuzzy
-				forM_ fields $ uncurry Annex.setField
-				when (cmdnomessages cmd) $ 
-					Annex.setOutput QuietOutput
-				sequence_ flags
-				whenM (annexDebug <$> Annex.getGitConfig) $
-					liftIO enableDebugOutput
-				startup
-				performCommandAction cmd params
-				shutdown $ cmdnocommit cmd
+	case getOptCmd args cmd commonoptions of
+		Right (flags, params) -> go flags params
+			=<< (E.try getgitrepo :: IO (Either E.SomeException Git.Repo))
+		Left parseerr -> error parseerr
   where
+	go flags params (Right g) = do
+		state <- Annex.new g
+		Annex.eval state $ do
+			checkEnvironment
+			when fuzzy $
+				inRepo $ autocorrect . Just
+			forM_ fields $ uncurry Annex.setField
+			when (cmdnomessages cmd) $ 
+				Annex.setOutput QuietOutput
+			sequence_ flags
+			whenM (annexDebug <$> Annex.getGitConfig) $
+				liftIO enableDebugOutput
+			startup
+			performCommandAction cmd params
+			shutdown $ cmdnocommit cmd
+	go _flags params (Left e) = do
+		when fuzzy $
+	 		autocorrect =<< Git.Config.global
+		maybe (throw e) (\a -> a params) (cmdnorepo cmd)
 	err msg = msg ++ "\n\n" ++ usage header allcmds
 	cmd = Prelude.head cmds
 	(fuzzy, cmds, name, args) = findCmd fuzzyok allargs allcmds err
-	(flags, params) = getOptCmd args cmd commonoptions
-	checkfuzzy = when fuzzy $
-		inRepo $ Git.AutoCorrect.prepare name cmdname cmds
+	autocorrect = Git.AutoCorrect.prepare name cmdname cmds
 
 {- Parses command line params far enough to find the Command to run, and
  - returns the remaining params.
@@ -81,12 +87,12 @@
 
 {- Parses command line options, and returns actions to run to configure flags
  - and the remaining parameters for the command. -}
-getOptCmd :: CmdParams -> Command -> [Option] -> ([Annex ()], CmdParams)
+getOptCmd :: CmdParams -> Command -> [Option] -> Either String ([Annex ()], CmdParams)
 getOptCmd argv cmd commonoptions = check $
 	getOpt Permute (commonoptions ++ cmdoptions cmd) argv
   where
-	check (flags, rest, []) = (flags, rest)
-	check (_, _, errs) = error $ unlines
+	check (flags, rest, []) = Right (flags, rest)
+	check (_, _, errs) = Left $ unlines
 		[ concat errs
 		, commandUsage cmd
 		]
diff --git a/CmdLine/GitAnnex.hs b/CmdLine/GitAnnex.hs
--- a/CmdLine/GitAnnex.hs
+++ b/CmdLine/GitAnnex.hs
@@ -96,8 +96,8 @@
 #endif
 import qualified Command.RemoteDaemon
 #endif
-#ifdef WITH_TESTSUITE
 import qualified Command.Test
+#ifdef WITH_TESTSUITE
 import qualified Command.FuzzTest
 import qualified Command.TestRemote
 #endif
@@ -188,8 +188,8 @@
 #endif
 	, Command.RemoteDaemon.def
 #endif
-#ifdef WITH_TESTSUITE
 	, Command.Test.def
+#ifdef WITH_TESTSUITE
 	, Command.FuzzTest.def
 	, Command.TestRemote.def
 #endif
diff --git a/Command/Drop.hs b/Command/Drop.hs
--- a/Command/Drop.hs
+++ b/Command/Drop.hs
@@ -55,8 +55,12 @@
 	showStart' ("drop " ++ Remote.name remote) key afile
 	next $ performRemote key afile numcopies remote
 
+-- Note that lockContent is called before checking if the key is present
+-- on enough remotes to allow removal. This avoids a scenario where two
+-- or more remotes are trying to remove a key at the same time, and each
+-- see the key is present on the other.
 performLocal :: Key -> AssociatedFile -> NumCopies -> Maybe Remote -> CommandPerform
-performLocal key afile numcopies knownpresentremote = lockContent key $ do
+performLocal key afile numcopies knownpresentremote = lockContent key $ \contentlock -> do
 	(remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
 	let trusteduuids' = case knownpresentremote of
 		Nothing -> trusteduuids
@@ -66,7 +70,7 @@
 	u <- getUUID
 	ifM (canDrop u key afile numcopies trusteduuids' tocheck [])
 		( do
-			removeAnnex key
+			removeAnnex contentlock
 			notifyDrop afile True
 			next $ cleanupLocal key
 		, do
@@ -75,7 +79,7 @@
 		)
 
 performRemote :: Key -> AssociatedFile -> NumCopies -> Remote -> CommandPerform
-performRemote key afile numcopies remote = lockContent key $ do
+performRemote key afile numcopies remote = do
 	-- Filter the remote it's being dropped from out of the lists of
 	-- places assumed to have the key, and places to check.
 	-- When the local repo has the key, that's one additional copy,
diff --git a/Command/DropKey.hs b/Command/DropKey.hs
--- a/Command/DropKey.hs
+++ b/Command/DropKey.hs
@@ -28,8 +28,8 @@
 	next $ perform key
 
 perform :: Key -> CommandPerform
-perform key = lockContent key $ do
-	removeAnnex key
+perform key = lockContent key $ \contentlock -> do
+	removeAnnex contentlock
 	next $ cleanup key
 
 cleanup :: Key -> CommandCleanup
diff --git a/Command/Import.hs b/Command/Import.hs
--- a/Command/Import.hs
+++ b/Command/Import.hs
@@ -90,7 +90,7 @@
 		handleexisting =<< liftIO (catchMaybeIO $ getSymbolicLinkStatus destfile)
 		liftIO $ createDirectoryIfMissing True (parentDir destfile)
 		liftIO $ if mode == Duplicate || mode == SkipDuplicates
-			then void $ copyFileExternal srcfile destfile
+			then void $ copyFileExternal CopyAllMetaData srcfile destfile
 			else moveFile srcfile destfile
 		Command.Add.perform destfile
 	handleexisting Nothing = noop
diff --git a/Command/Move.hs b/Command/Move.hs
--- a/Command/Move.hs
+++ b/Command/Move.hs
@@ -91,7 +91,7 @@
 	return $ dest `elem` remotes
 
 toPerform :: Remote -> Bool -> Key -> AssociatedFile -> Bool -> Either String Bool -> CommandPerform
-toPerform dest move key afile fastcheck isthere = moveLock move key $
+toPerform dest move key afile fastcheck isthere = do
 	case isthere of
 		Left err -> do
 			showNote err
@@ -115,8 +115,8 @@
 			finish
   where
 	finish
-		| move = do
-			removeAnnex key
+		| move = lockContent key $ \contentlock -> do
+			removeAnnex contentlock
 			next $ Command.Drop.cleanupLocal key
 		| otherwise = next $ return True
 
@@ -150,11 +150,10 @@
 		return $ u /= Remote.uuid src && elem src remotes
 
 fromPerform :: Remote -> Bool -> Key -> AssociatedFile -> CommandPerform
-fromPerform src move key afile = moveLock move key $
-	ifM (inAnnex key)
-		( dispatch move True
-		, dispatch move =<< go
-		)
+fromPerform src move key afile = ifM (inAnnex key)
+	( dispatch move True
+	, dispatch move =<< go
+	)
   where
 	go = notifyTransfer Download afile $ 
 		download (Remote.uuid src) key afile noRetry $ \p -> do
@@ -165,9 +164,3 @@
 	dispatch True True = do -- finish moving
 		ok <- Remote.removeKey src key
 		next $ Command.Drop.cleanupRemote key src ok
-
-{- Locks a key in order for it to be moved.
- - No lock is needed when a key is being copied. -}
-moveLock :: Bool -> Key -> Annex a -> Annex a
-moveLock True key a = lockContent key a
-moveLock False _ a = a
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -18,16 +18,12 @@
 import Annex.Hook
 import Annex.View
 import Annex.View.ViewedFile
-import Annex.Perms
+import Annex.LockFile
 import Logs.View
 import Logs.MetaData
 import Types.View
 import Types.MetaData
 
-#ifdef mingw32_HOST_OS
-import Utility.WinLock
-#endif
-
 import qualified Data.Set as S
 
 def :: [Command]
@@ -92,19 +88,4 @@
 
 {- Takes exclusive lock; blocks until available. -}
 lockPreCommitHook :: Annex a -> Annex a
-lockPreCommitHook a = do
-	lockfile <- fromRepo gitAnnexPreCommitLock
-	createAnnexDirectory $ takeDirectory lockfile
-	mode <- annexFileMode
-	bracketIO (lock lockfile mode) unlock (const a)
-  where
-#ifndef mingw32_HOST_OS
-	lock lockfile mode = do
-		l <- liftIO $ noUmask mode $ createFile lockfile mode
-		liftIO $ waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
-		return l
-	unlock = closeFd
-#else
-	lock lockfile _mode = liftIO $ waitToLock $  lockExclusive lockfile
-	unlock = dropLock
-#endif
+lockPreCommitHook = withExclusiveLock gitAnnexPreCommitLock
diff --git a/Command/TestRemote.hs b/Command/TestRemote.hs
--- a/Command/TestRemote.hs
+++ b/Command/TestRemote.hs
@@ -114,7 +114,7 @@
 	, check "storeKey when already present" store
 	, present True
 	, check "retrieveKeyFile" $ do
-		removeAnnex k
+		lockContent k removeAnnex
 		get
 	, check "fsck downloaded object" fsck
 	, check "retrieveKeyFile resume from 33%" $ do
@@ -124,20 +124,20 @@
 			sz <- hFileSize h
 			L.hGet h $ fromInteger $ sz `div` 3
 		liftIO $ L.writeFile tmp partial
-		removeAnnex k
+		lockContent k removeAnnex
 		get
 	, check "fsck downloaded object" fsck
 	, check "retrieveKeyFile resume from 0" $ do
 		tmp <- prepTmp k
 		liftIO $ writeFile tmp ""
-		removeAnnex k
+		lockContent k removeAnnex
 		get
 	, check "fsck downloaded object" fsck
 	, check "retrieveKeyFile resume from end" $ do
 		loc <- Annex.calcRepo (gitAnnexLocation k)
 		tmp <- prepTmp k
-		void $ liftIO $ copyFileExternal loc tmp
-		removeAnnex k
+		void $ liftIO $ copyFileExternal CopyAllMetaData loc tmp
+		lockContent k removeAnnex
 		get
 	, check "fsck downloaded object" fsck
 	, check "removeKey when present" remove
@@ -183,7 +183,7 @@
 cleanup :: [Remote] -> [Key] -> Bool -> CommandCleanup
 cleanup rs ks ok = do
 	forM_ rs $ \r -> forM_ ks (Remote.removeKey r)
-	forM_ ks removeAnnex
+	forM_ ks $ \k -> lockContent k removeAnnex
 	return ok
 
 chunkSizes :: Int -> Bool -> [Int]
diff --git a/Command/Unannex.hs b/Command/Unannex.hs
--- a/Command/Unannex.hs
+++ b/Command/Unannex.hs
@@ -89,7 +89,7 @@
 		)
   where
 	copyfrom src = 
-		thawContent file `after` liftIO (copyFileExternal src file)
+		thawContent file `after` liftIO (copyFileExternal CopyAllMetaData src file)
 	hardlinkfrom src =
 #ifndef mingw32_HOST_OS
 		-- creating a hard link could fall; fall back to copying
diff --git a/Command/Uninit.hs b/Command/Uninit.hs
--- a/Command/Uninit.hs
+++ b/Command/Uninit.hs
@@ -103,7 +103,7 @@
   	go c [] = return c
 	go c (k:ks) = ifM (inAnnexCheck k $ liftIO . enoughlinks)
 		( do
-			removeAnnex k
+			lockContent k removeAnnex
 			go c ks
 		, go (k:c) ks
 		)
diff --git a/Command/Unlock.hs b/Command/Unlock.hs
--- a/Command/Unlock.hs
+++ b/Command/Unlock.hs
@@ -46,7 +46,7 @@
 	tmpdest <- fromRepo $ gitAnnexTmpObjectLocation key
 	liftIO $ createDirectoryIfMissing True (parentDir tmpdest)
 	showAction "copying"
-	ifM (liftIO $ copyFileExternal src tmpdest)
+	ifM (liftIO $ copyFileExternal CopyAllMetaData src tmpdest)
 		( do
 			liftIO $ do
 				removeFile dest
diff --git a/Git/AutoCorrect.hs b/Git/AutoCorrect.hs
--- a/Git/AutoCorrect.hs
+++ b/Git/AutoCorrect.hs
@@ -41,9 +41,9 @@
 
 {- Takes action based on git's autocorrect configuration, in preparation for
  - an autocorrected command being run. -}
-prepare :: String -> (c -> String) -> [c] -> Repo -> IO ()
+prepare :: String -> (c -> String) -> [c] -> Maybe Repo -> IO ()
 prepare input showmatch matches r =
-	case readish $ Git.Config.get "help.autocorrect" "0" r of
+	case readish . Git.Config.get "help.autocorrect" "0" =<< r of
 		Just n
 			| n == 0 -> list
 			| n < 0 -> warn
diff --git a/Logs/Transfer.hs b/Logs/Transfer.hs
--- a/Logs/Transfer.hs
+++ b/Logs/Transfer.hs
@@ -17,9 +17,7 @@
 import Utility.Percentage
 import Utility.QuickCheck
 import Utility.PID
-#ifdef mingw32_HOST_OS
-import Utility.WinLock
-#endif
+import Utility.LockFile
 
 import Data.Time.Clock
 import Data.Time.Clock.POSIX
@@ -131,19 +129,12 @@
 checkTransfer t = do
 	tfile <- fromRepo $ transferFile t
 #ifndef mingw32_HOST_OS
-	mode <- annexFileMode
-	mfd <- liftIO $ catchMaybeIO $
-		openFd (transferLockFile tfile) ReadOnly (Just mode) defaultFileFlags
-	case mfd of
-		Nothing -> return Nothing -- failed to open file; not running
-		Just fd -> do
-			locked <- liftIO $
-				getLock fd (WriteLock, AbsoluteSeek, 0, 0)
-			liftIO $ closeFd fd
-			case locked of
-				Nothing -> return Nothing
-				Just (pid, _) -> liftIO $ catchDefaultIO Nothing $
-					readTransferInfoFile (Just pid) tfile
+	liftIO $ do
+		v <- getLockStatus (transferLockFile tfile)
+		case v of
+			Just (pid, _) -> catchDefaultIO Nothing $
+				readTransferInfoFile (Just pid) tfile
+			Nothing -> return Nothing
 #else
 	v <- liftIO $ lockShared $ transferLockFile tfile
 	liftIO $ case v of
diff --git a/Remote/Git.hs b/Remote/Git.hs
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -51,6 +51,7 @@
 import qualified Remote.GCrypt
 import Config.Files
 import Creds
+import Annex.CatFile
 
 import Control.Concurrent
 import Control.Concurrent.MSampleVar
@@ -338,8 +339,8 @@
 			commitOnCleanup r $ onLocal r $ do
 				ensureInitialized
 				whenM (Annex.Content.inAnnex key) $ do
-					Annex.Content.lockContent key $
-						Annex.Content.removeAnnex key
+					Annex.Content.lockContent key
+						Annex.Content.removeAnnex
 					logStatus key InfoMissing
 					Annex.Content.saveState True
 				return True
@@ -500,6 +501,8 @@
 {- Runs an action from the perspective of a local remote.
  -
  - The AnnexState is cached for speed and to avoid resource leaks.
+ - However, catFileStop is called to avoid git-cat-file processes hanging
+ - around on removable media.
  -
  - The repository's git-annex branch is not updated, as an optimisation.
  - No caller of onLocal can query data from the branch and be ensured
@@ -520,7 +523,8 @@
 	cache st = Annex.changeState $ \s -> s
 		{ Annex.remoteannexstate = M.insert (uuid r) st (Annex.remoteannexstate s) }
 	go st a' = do
-		(ret, st') <- liftIO $ Annex.run st a'
+		(ret, st') <- liftIO $ Annex.run st $
+			catFileStop `after` a'
 		cache st'
 		return ret
 
@@ -539,7 +543,7 @@
 	docopy = liftIO $ bracket
 		(forkIO $ watchfilesize zeroBytesProcessed)
 		(void . tryIO . killThread)
-		(const $ copyFileExternal src dest)
+		(const $ copyFileExternal CopyTimeStamps src dest)
 	watchfilesize oldsz = do
 		threadDelay 500000 -- 0.5 seconds
 		v <- catchMaybeIO $
diff --git a/Remote/Helper/Hooks.hs b/Remote/Helper/Hooks.hs
--- a/Remote/Helper/Hooks.hs
+++ b/Remote/Helper/Hooks.hs
@@ -16,10 +16,9 @@
 import Types.CleanupActions
 import qualified Annex
 import Annex.LockFile
+import Utility.LockFile
 #ifndef mingw32_HOST_OS
 import Annex.Perms
-#else
-import Utility.WinLock
 #endif
 
 {- Modifies a remote's access functions to first run the
@@ -84,19 +83,12 @@
 		unlockFile lck
 #ifndef mingw32_HOST_OS
 		mode <- annexFileMode
-		fd <- liftIO $ noUmask mode $
-			openFd lck ReadWrite (Just mode) defaultFileFlags
-		v <- liftIO $ tryIO $
-			setLock fd (WriteLock, AbsoluteSeek, 0, 0)
-		case v of
-			Left _ -> noop
-			Right _ -> run stophook
-		liftIO $ closeFd fd
+		v <- liftIO $ noUmask mode $ tryLockExclusive (Just mode) lck
 #else
 		v <- liftIO $ lockExclusive lck
+#endif
 		case v of
 			Nothing -> noop
 			Just lockhandle -> do
 				run stophook
 				liftIO $ dropLock lockhandle
-#endif
diff --git a/Types/LockPool.hs b/Types/LockPool.hs
--- a/Types/LockPool.hs
+++ b/Types/LockPool.hs
@@ -5,20 +5,12 @@
  - Licensed under the GNU GPL version 3 or higher.
  -}
 
-{-# LANGUAGE CPP #-}
-
 module Types.LockPool (
 	LockPool,
 	LockHandle
 ) where
 
 import qualified Data.Map as M
-
-#ifndef mingw32_HOST_OS
-import System.Posix.Types (Fd)
-type LockHandle = Fd
-#else
-import Utility.WinLock -- defines LockHandle
-#endif
+import Utility.LockFile
 
 type LockPool = M.Map FilePath LockHandle
diff --git a/Utility/CopyFile.hs b/Utility/CopyFile.hs
--- a/Utility/CopyFile.hs
+++ b/Utility/CopyFile.hs
@@ -1,6 +1,6 @@
 {- file copying
  -
- - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
+ - Copyright 2010-2014 Joey Hess <joey@kitenet.net>
  -
  - License: BSD-2-clause
  -}
@@ -9,16 +9,20 @@
 
 module Utility.CopyFile (
 	copyFileExternal,
-	createLinkOrCopy
+	createLinkOrCopy,
+	CopyMetaData(..)
 ) where
 
 import Common
 import qualified Build.SysConfig as SysConfig
 
+data CopyMetaData = CopyTimeStamps | CopyAllMetaData
+	deriving (Eq)
+
 {- The cp command is used, because I hate reinventing the wheel,
  - and because this allows easy access to features like cp --reflink. -}
-copyFileExternal :: FilePath -> FilePath -> IO Bool
-copyFileExternal src dest = do
+copyFileExternal :: CopyMetaData -> FilePath -> FilePath -> IO Bool
+copyFileExternal meta src dest = do
 	whenM (doesFileExist dest) $
 		removeFile dest
 	boolSystem "cp" $ params ++ [File src, File dest]
@@ -26,12 +30,16 @@
 #ifndef __ANDROID__
 	params = map snd $ filter fst
 		[ (SysConfig.cp_reflink_auto, Param "--reflink=auto")
-		, (SysConfig.cp_a, Param "-a")
-		, (SysConfig.cp_p && not SysConfig.cp_a, Param "-p")
+		, (allmeta && SysConfig.cp_a, Param "-a")
+		, (allmeta && SysConfig.cp_p && not SysConfig.cp_a
+			, Param "-p")
+		, (not allmeta && SysConfig.cp_preserve_timestamps
+			, Param "--preserve=timestamps")
 		]
 #else
 	params = []
 #endif
+	allmeta = meta == CopyAllMetaData
 
 {- Create a hard link if the filesystem allows it, and fall back to copying
  - the file. -}
@@ -42,7 +50,7 @@
   	go = do
 		createLink src dest
 		return True
-  	fallback = copyFileExternal src dest
+  	fallback = copyFileExternal CopyAllMetaData src dest
 #else
-createLinkOrCopy = copyFileExternal
+createLinkOrCopy = copyFileExternal CopyAllMetaData
 #endif
diff --git a/Utility/Daemon.hs b/Utility/Daemon.hs
--- a/Utility/Daemon.hs
+++ b/Utility/Daemon.hs
@@ -15,7 +15,7 @@
 import Utility.LogFile
 #else
 import Utility.WinProcess
-import Utility.WinLock
+import Utility.LockFile
 #endif
 
 #ifndef mingw32_HOST_OS
diff --git a/Utility/LockFile.hs b/Utility/LockFile.hs
new file mode 100644
--- /dev/null
+++ b/Utility/LockFile.hs
@@ -0,0 +1,20 @@
+{- Lock files
+ -
+ - Posix and Windows lock files are extremely different.
+ - This module does *not* attempt to be a portability shim, it just exposes
+ - the native locking of the OS.
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - License: BSD-2-clause
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Utility.LockFile (module X) where
+
+#ifndef mingw32_HOST_OS
+import Utility.LockFile.Posix as X
+#else
+import Utility.LockFile.Windows as X
+#endif
diff --git a/Utility/LockFile/Posix.hs b/Utility/LockFile/Posix.hs
new file mode 100644
--- /dev/null
+++ b/Utility/LockFile/Posix.hs
@@ -0,0 +1,99 @@
+{- Posix lock files
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - License: BSD-2-clause
+ -}
+
+module Utility.LockFile.Posix (
+	LockHandle,
+	lockShared,
+	lockExclusive,
+	tryLockExclusive,
+	createLockFile,
+	openExistingLockFile,
+	isLocked,
+	checkLocked,
+	getLockStatus,
+	dropLock,
+) where
+
+import Utility.Exception
+import Utility.Applicative
+
+import System.IO
+import System.Posix
+import Data.Maybe
+
+type LockFile = FilePath
+
+newtype LockHandle = LockHandle Fd
+
+-- Takes a shared lock, blocking until the lock is available.
+lockShared :: Maybe FileMode -> LockFile -> IO LockHandle
+lockShared = lock ReadLock
+
+-- Takes an exclusive lock, blocking until the lock is available.
+lockExclusive :: Maybe FileMode -> LockFile -> IO LockHandle
+lockExclusive = lock WriteLock
+
+-- Tries to take an exclusive lock, but does not block.
+tryLockExclusive :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
+tryLockExclusive mode lockfile = do
+	l <- openLockFile mode lockfile
+	v <- tryIO $ setLock l (WriteLock, AbsoluteSeek, 0, 0)
+	case v of
+		Left _ -> do
+			closeFd l
+			return Nothing
+		Right _ -> return $ Just $ LockHandle l
+
+-- Setting the FileMode allows creation of a new lock file.
+-- If it's Nothing then this only succeeds when the lock file already exists.
+lock :: LockRequest -> Maybe FileMode -> LockFile -> IO LockHandle
+lock lockreq mode lockfile = do
+	l <- openLockFile mode lockfile
+	waitToSetLock l (lockreq, AbsoluteSeek, 0, 0)
+	return (LockHandle l)
+
+-- Create and opens lock file; does not lock it.
+createLockFile :: FileMode -> LockFile -> IO Fd
+createLockFile filemode = openLockFile (Just filemode)
+
+-- Opens an existing lock file; does not lock it, and if it does not exist,
+-- returns Nothing.
+openExistingLockFile :: LockFile -> IO (Maybe Fd)
+openExistingLockFile = catchMaybeIO . openLockFile Nothing
+
+-- Close on exec flag is set so child processes do not inherit the lock.
+openLockFile :: Maybe FileMode -> LockFile -> IO Fd
+openLockFile filemode lockfile = do
+	l <- openFd lockfile ReadWrite filemode defaultFileFlags
+	setFdOption l CloseOnExec True
+	return l
+
+-- Check if a file is locked, either exclusively, or with shared lock.
+-- When the file doesn't exist, it's considered not locked.
+isLocked :: LockFile -> IO Bool
+isLocked = fromMaybe False <$$> checkLocked
+
+-- Returns Nothing when the file doesn't exist, for cases where
+-- that is different from it not being locked.
+checkLocked :: LockFile -> IO (Maybe Bool)
+checkLocked = maybe Nothing (Just . isJust) <$$> getLockStatus'
+
+getLockStatus :: LockFile -> IO (Maybe (ProcessID, FileLock))
+getLockStatus = fromMaybe Nothing <$$> getLockStatus'
+
+getLockStatus' :: LockFile -> IO (Maybe (Maybe (ProcessID, FileLock)))
+getLockStatus' lockfile = go =<< catchMaybeIO open
+  where
+	open = openFd lockfile ReadOnly Nothing defaultFileFlags
+	go Nothing = return Nothing
+	go (Just h) = do
+		ret <- getLock h (ReadLock, AbsoluteSeek, 0, 0)
+		closeFd h
+		return (Just ret)
+
+dropLock :: LockHandle -> IO ()
+dropLock (LockHandle fd) = closeFd fd
diff --git a/Utility/LockFile/Windows.hs b/Utility/LockFile/Windows.hs
new file mode 100644
--- /dev/null
+++ b/Utility/LockFile/Windows.hs
@@ -0,0 +1,75 @@
+{- Windows lock files
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - License: BSD-2-clause
+ -}
+
+module Utility.LockFile.Windows (
+	lockShared,
+	lockExclusive,
+	dropLock,
+	waitToLock,
+	LockHandle
+) where
+
+import System.Win32.Types
+import System.Win32.File
+import Control.Concurrent
+
+type LockFile = FilePath
+
+type LockHandle = HANDLE
+
+{- Tries to lock a file with a shared lock, which allows other processes to
+ - also lock it shared. Fails is the file is exclusively locked. -}
+lockShared :: LockFile -> IO (Maybe LockHandle)
+lockShared = openLock fILE_SHARE_READ
+
+{- Tries to take an exclusive lock on a file. Fails if another process has
+ - a shared or exclusive lock.
+ -
+ - Note that exclusive locking also prevents the file from being opened for
+ - read or write by any other progess. So for advisory locking of a file's
+ - content, a different LockFile should be used. -}
+lockExclusive :: LockFile -> IO (Maybe LockHandle)
+lockExclusive = openLock fILE_SHARE_NONE
+
+{- Windows considers just opening a file enough to lock it. This will
+ - create the LockFile if it does not already exist.
+ -
+ - Will fail if the file is already open with an incompatable ShareMode.
+ - Note that this may happen if an unrelated process, such as a virus
+ - scanner, even looks at the file. See http://support.microsoft.com/kb/316609
+ -
+ - Note that createFile busy-waits to try to avoid failing when some other
+ - process briefly has a file open. But that would make checking locks
+ - much more expensive, so is not done here. Thus, the use of c_CreateFile.
+ -
+ - Also, passing Nothing for SECURITY_ATTRIBUTES ensures that the lock file
+ - is not inheerited by any child process.
+ -}
+openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
+openLock sharemode f = do
+	h <- withTString f $ \c_f ->
+		c_CreateFile c_f gENERIC_READ sharemode security_attributes
+			oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL (maybePtr Nothing)
+	return $ if h == iNVALID_HANDLE_VALUE
+		then Nothing
+		else Just h
+  where
+	security_attributes = maybePtr Nothing
+
+dropLock :: LockHandle -> IO ()
+dropLock = closeHandle
+
+{- If the initial lock fails, this is a BUSY wait, and does not
+ - guarentee FIFO order of waiters. In other news, Windows is a POS. -}
+waitToLock :: IO (Maybe LockHandle) -> IO LockHandle
+waitToLock locker = takelock
+  where
+	takelock = go =<< locker
+	go (Just lck) = return lck
+	go Nothing = do
+		threadDelay (500000) -- half a second
+		takelock
diff --git a/Utility/Url.hs b/Utility/Url.hs
--- a/Utility/Url.hs
+++ b/Utility/Url.hs
@@ -7,6 +7,7 @@
 
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
 
 module Utility.Url (
 	URLString,
@@ -42,7 +43,11 @@
 	{ userAgent :: Maybe UserAgent
 	, reqHeaders :: Headers
 	, reqParams :: [CommandParam]
+#if MIN_VERSION_http_conduit(2,0,0)
 	, applyRequest :: Request -> Request
+#else
+	, applyRequest :: forall m. Request m -> Request m
+#endif
 	}
 
 instance Default UrlOptions
@@ -142,7 +147,11 @@
 			liftIO $ closeManager mgr
 			return ret
 
+#if MIN_VERSION_http_conduit(2,0,0)
 headRequest :: Request -> Request
+#else
+headRequest :: Request m -> Request m
+#endif
 headRequest r = r
 	{ method = methodHead
 	-- remove defaut Accept-Encoding header, to get actual,
@@ -151,8 +160,6 @@
 		filter (\(h, _) -> h /= hAcceptEncoding)
 		(requestHeaders r)
 	}
-  where
-	hAcceptEncoding = "Accept-Encoding"
 
 {- Used to download large files, such as the contents of keys.
  -
@@ -206,3 +213,14 @@
 {- Allows for spaces and other stuff in urls, properly escaping them. -}
 parseURIRelaxed :: URLString -> Maybe URI
 parseURIRelaxed = parseURI . escapeURIString isAllowedInURI
+
+hAcceptEncoding :: CI.CI B.ByteString
+hAcceptEncoding = "Accept-Encoding"
+
+#if ! MIN_VERSION_http_types(0,7,0)
+hContentLength :: CI.CI B.ByteString
+hContentLength = "Content-Length"
+
+hUserAgent :: CI.CI B.ByteString
+hUserAgent = "User-Agent"
+#endif
diff --git a/Utility/WinLock.hs b/Utility/WinLock.hs
deleted file mode 100644
--- a/Utility/WinLock.hs
+++ /dev/null
@@ -1,69 +0,0 @@
-{- Windows lock files
- -
- - Copyright 2014 Joey Hess <joey@kitenet.net>
- -
- - License: BSD-2-clause
- -}
-
-module Utility.WinLock (
-	lockShared,
-	lockExclusive,
-	dropLock,
-	waitToLock,
-	LockHandle
-) where
-
-import System.Win32.Types
-import System.Win32.File
-import Control.Concurrent
-
-{- Locking is exclusive, and prevents the file from being opened for read
- - or write by any other process. So for advisory locking of a file, a
- - different LockFile should be used. -}
-type LockFile = FilePath
-
-type LockHandle = HANDLE
-
-{- Tries to lock a file with a shared lock, which allows other processes to
- - also lock it shared. Fails is the file is exclusively locked. -}
-lockShared :: LockFile -> IO (Maybe LockHandle)
-lockShared = openLock fILE_SHARE_READ
-
-{- Tries to take an exclusive lock on a file. Fails if another process has
- - a shared or exclusive lock. -}
-lockExclusive :: LockFile -> IO (Maybe LockHandle)
-lockExclusive = openLock fILE_SHARE_NONE
-
-{- Windows considers just opening a file enough to lock it. This will
- - create the LockFile if it does not already exist.
- -
- - Will fail if the file is already open with an incompatable ShareMode.
- - Note that this may happen if an unrelated process, such as a virus
- - scanner, even looks at the file. See http://support.microsoft.com/kb/316609
- -
- - Note that createFile busy-waits to try to avoid failing when some other
- - process briefly has a file open. But that would make checking locks
- - much more expensive, so is not done here. Thus, the use of c_CreateFile.
- -}
-openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
-openLock sharemode f = do
-	h <- withTString f $ \c_f ->
-		c_CreateFile c_f gENERIC_READ sharemode (maybePtr Nothing)
-			oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL (maybePtr Nothing)
-	return $ if h == iNVALID_HANDLE_VALUE
-		then Nothing
-		else Just h
-
-dropLock :: LockHandle -> IO ()
-dropLock = closeHandle
-
-{- If the initial lock fails, this is a BUSY wait, and does not
- - guarentee FIFO order of waiters. In other news, Windows is a POS. -}
-waitToLock :: IO (Maybe LockHandle) -> IO LockHandle
-waitToLock locker = takelock
-  where
-	takelock = go =<< locker
-	go (Just lck) = return lck
-	go Nothing = do
-		threadDelay (500000) -- half a second
-		takelock
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,19 @@
+git-annex (5.20140831) unstable; urgency=medium
+
+  * Make --help work when not in a git repository. Closes: #758592
+  * Ensure that all lock fds are close-on-exec, fixing various problems with
+    them being inherited by child processes such as git commands.
+  * When accessing a local remote, shut down git-cat-file processes
+    afterwards, to ensure that remotes on removable media can be unmounted.
+    Closes: #758630
+  * Fix handing of autocorrection when running outside a git repository.
+  * Fix stub git-annex test support when built without tasty.
+  * Do not preserve permissions and acls when copying files from
+    one local git repository to another. Timestamps are still preserved
+    as long as cp --preserve=timestamps is supported. Closes: #729757
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 31 Aug 2014 12:30:08 -0700
+
 git-annex (5.20140817) unstable; urgency=medium
 
   * New chunk= option to chunk files stored in special remotes.
diff --git a/debian/control b/debian/control
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,7 @@
 	libghc-dav-dev (>= 1.0) [amd64 i386 kfreebsd-amd64 kfreebsd-i386 powerpc],
 	libghc-quickcheck2-dev,
 	libghc-monad-control-dev (>= 0.3),
-	libghc-exceptions-dev,
+	libghc-exceptions-dev (>= 0.6),
 	libghc-transformers-dev,
 	libghc-unix-compat-dev,
 	libghc-dlist-dev,
@@ -31,16 +31,16 @@
 	libghc-stm-dev (>= 2.3),
 	libghc-dbus-dev (>= 0.10.3) [linux-any],
 	libghc-fdo-notify-dev (>= 0.3) [linux-any],
-	libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-yesod-default-dev [i386 amd64 kfreebsd-amd64 powerpc sparc],
-	libghc-hamlet-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-shakespeare-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-clientsession-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-warp-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-warp-tls-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-wai-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
-	libghc-wai-extra-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
+	libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-yesod-default-dev [i386 amd64 kfreebsd-amd64 powerpc],
+	libghc-hamlet-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-shakespeare-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-clientsession-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-warp-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-warp-tls-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-wai-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
+	libghc-wai-extra-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc],
 	libghc-securemem-dev,
 	libghc-byteable-dev,
 	libghc-dns-dev,
@@ -59,12 +59,12 @@
 	libghc-feed-dev (>= 0.3.9.2),
 	libghc-regex-tdfa-dev [!mipsel !s390],
 	libghc-regex-compat-dev [mipsel s390],
-	libghc-tasty-dev (>= 0.7) [!mipsel !sparc],
-	libghc-tasty-hunit-dev [!mipsel !sparc],
-	libghc-tasty-quickcheck-dev [!mipsel !sparc],
-	libghc-tasty-rerun-dev [!mipsel !sparc],
+	libghc-tasty-dev (>= 0.7) [!sparc],
+	libghc-tasty-hunit-dev [!sparc],
+	libghc-tasty-quickcheck-dev [!sparc],
+	libghc-tasty-rerun-dev [!sparc],
 	libghc-optparse-applicative-dev [!sparc],
-	lsof [!kfreebsd-i386 !kfreebsd-amd64],
+	lsof [!kfreebsd-i386 !kfreebsd-amd64 !hurd-any],
 	ikiwiki,
 	perlmagick,
 	git (>= 1:1.8.4),
diff --git a/doc/bugs/Android_4.4_install_fails_with_permission_denied_errors.mdwn b/doc/bugs/Android_4.4_install_fails_with_permission_denied_errors.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/Android_4.4_install_fails_with_permission_denied_errors.mdwn
@@ -0,0 +1,295 @@
+### Please describe the problem.
+
+Installing git-annex on a new Nexus 5 with Android 4.4.4 using [Android 4.4 and 4.3 git-annex.apk](http://downloads.kitenet.net/git-annex/android/current/4.3/git-annex.apk) does not give me a working git-annex environment. It seems permission is denied to install many of the app files.
+
+
+### What steps will reproduce the problem?
+
+1. Install git-annex
+2. From within `adb shell`, run: `/data/data/ga.androidterm/runshell`
+3. Try one of the included programs, e.g., `git`
+
+
+### What version of git-annex are you using? On what operating system?
+
+The current (as of 2014-08-30) git-annex for Android 4.3 and up on Android 4.4.4.
+
+
+### Please provide any additional information below.
+
+Running `/data/data/ga.androidterm/runshell` from `adb shell` gives me:
+
+[[!format txt """
+shell@hammerhead:/ $ /data/data/ga.androidterm/runshell                        
+Falling back to hardcoded app location; cannot find expected files in /data/app-lib
+shell@hammerhead:/sdcard/git-annex.home $ ls
+git-annex-install.log
+shell@hammerhead:/sdcard/git-annex.home $ cat git-annex-install.log
+Installation starting to /data/data/ga.androidterm
+71c22504d777380dd59d2128b97715fde9ef6bec
+mv: can't rename '/data/data/ga.androidterm/bin': Permission denied
+installing busybox
+ln: /data/data/ga.androidterm/bin/busybox: Permission denied
+installing git-annex
+ln: /data/data/ga.androidterm/bin/git-annex: Permission denied
+installing git-shell
+ln: /data/data/ga.androidterm/bin/git-shell: Permission denied
+installing git-upload-pack
+ln: /data/data/ga.androidterm/bin/git-upload-pack: Permission denied
+installing git
+ln: /data/data/ga.androidterm/bin/git: Permission denied
+installing gpg
+ln: /data/data/ga.androidterm/bin/gpg: Permission denied
+installing rsync
+ln: /data/data/ga.androidterm/bin/rsync: Permission denied
+installing ssh
+ln: /data/data/ga.androidterm/bin/ssh: Permission denied
+installing ssh-keygen
+ln: /data/data/ga.androidterm/bin/ssh-keygen: Permission denied
+busybox: /data/data/ga.androidterm/bin/[: Permission denied
+busybox: /data/data/ga.androidterm/bin/[[: Permission denied
+busybox: /data/data/ga.androidterm/bin/ar: Permission denied
+busybox: /data/data/ga.androidterm/bin/arp: Permission denied
+busybox: /data/data/ga.androidterm/bin/ash: Permission denied
+busybox: /data/data/ga.androidterm/bin/base64: Permission denied
+busybox: /data/data/ga.androidterm/bin/basename: Permission denied
+busybox: /data/data/ga.androidterm/bin/beep: Permission denied
+busybox: /data/data/ga.androidterm/bin/blkid: Permission denied
+busybox: /data/data/ga.androidterm/bin/blockdev: Permission denied
+busybox: /data/data/ga.androidterm/bin/bunzip2: Permission denied
+busybox: /data/data/ga.androidterm/bin/bzcat: Permission denied
+busybox: /data/data/ga.androidterm/bin/bzip2: Permission denied
+busybox: /data/data/ga.androidterm/bin/cal: Permission denied
+busybox: /data/data/ga.androidterm/bin/cat: Permission denied
+busybox: /data/data/ga.androidterm/bin/catv: Permission denied
+busybox: /data/data/ga.androidterm/bin/chat: Permission denied
+busybox: /data/data/ga.androidterm/bin/chattr: Permission denied
+busybox: /data/data/ga.androidterm/bin/chgrp: Permission denied
+busybox: /data/data/ga.androidterm/bin/chmod: Permission denied
+busybox: /data/data/ga.androidterm/bin/chown: Permission denied
+busybox: /data/data/ga.androidterm/bin/chpst: Permission denied
+busybox: /data/data/ga.androidterm/bin/chroot: Permission denied
+busybox: /data/data/ga.androidterm/bin/chrt: Permission denied
+busybox: /data/data/ga.androidterm/bin/chvt: Permission denied
+busybox: /data/data/ga.androidterm/bin/cksum: Permission denied
+busybox: /data/data/ga.androidterm/bin/clear: Permission denied
+busybox: /data/data/ga.androidterm/bin/cmp: Permission denied
+busybox: /data/data/ga.androidterm/bin/comm: Permission denied
+busybox: /data/data/ga.androidterm/bin/cp: Permission denied
+busybox: /data/data/ga.androidterm/bin/cpio: Permission denied
+busybox: /data/data/ga.androidterm/bin/cttyhack: Permission denied
+busybox: /data/data/ga.androidterm/bin/cut: Permission denied
+busybox: /data/data/ga.androidterm/bin/dc: Permission denied
+busybox: /data/data/ga.androidterm/bin/dd: Permission denied
+busybox: /data/data/ga.androidterm/bin/deallocvt: Permission denied
+busybox: /data/data/ga.androidterm/bin/devmem: Permission denied
+busybox: /data/data/ga.androidterm/bin/diff: Permission denied
+busybox: /data/data/ga.androidterm/bin/dirname: Permission denied
+busybox: /data/data/ga.androidterm/bin/dmesg: Permission denied
+busybox: /data/data/ga.androidterm/bin/dnsd: Permission denied
+busybox: /data/data/ga.androidterm/bin/dos2unix: Permission denied
+busybox: /data/data/ga.androidterm/bin/dpkg: Permission denied
+busybox: /data/data/ga.androidterm/bin/dpkg-deb: Permission denied
+busybox: /data/data/ga.androidterm/bin/du: Permission denied
+busybox: /data/data/ga.androidterm/bin/dumpkmap: Permission denied
+busybox: /data/data/ga.androidterm/bin/echo: Permission denied
+busybox: /data/data/ga.androidterm/bin/envdir: Permission denied
+busybox: /data/data/ga.androidterm/bin/envuidgid: Permission denied
+busybox: /data/data/ga.androidterm/bin/expand: Permission denied
+busybox: /data/data/ga.androidterm/bin/fakeidentd: Permission denied
+busybox: /data/data/ga.androidterm/bin/false: Permission denied
+busybox: /data/data/ga.androidterm/bin/fbset: Permission denied
+busybox: /data/data/ga.androidterm/bin/fbsplash: Permission denied
+busybox: /data/data/ga.androidterm/bin/fdflush: Permission denied
+busybox: /data/data/ga.androidterm/bin/fdformat: Permission denied
+busybox: /data/data/ga.androidterm/bin/fdisk: Permission denied
+busybox: /data/data/ga.androidterm/bin/fgconsole: Permission denied
+busybox: /data/data/ga.androidterm/bin/find: Permission denied
+busybox: /data/data/ga.androidterm/bin/findfs: Permission denied
+busybox: /data/data/ga.androidterm/bin/flash_lock: Permission denied
+busybox: /data/data/ga.androidterm/bin/flash_unlock: Permission denied
+busybox: /data/data/ga.androidterm/bin/flashcp: Permission denied
+busybox: /data/data/ga.androidterm/bin/flock: Permission denied
+busybox: /data/data/ga.androidterm/bin/fold: Permission denied
+busybox: /data/data/ga.androidterm/bin/freeramdisk: Permission denied
+busybox: /data/data/ga.androidterm/bin/ftpd: Permission denied
+busybox: /data/data/ga.androidterm/bin/ftpget: Permission denied
+busybox: /data/data/ga.androidterm/bin/ftpput: Permission denied
+busybox: /data/data/ga.androidterm/bin/fuser: Permission denied
+busybox: /data/data/ga.androidterm/bin/getopt: Permission denied
+busybox: /data/data/ga.androidterm/bin/grep: Permission denied
+busybox: /data/data/ga.androidterm/bin/gunzip: Permission denied
+busybox: /data/data/ga.androidterm/bin/gzip: Permission denied
+busybox: /data/data/ga.androidterm/bin/hd: Permission denied
+busybox: /data/data/ga.androidterm/bin/hdparm: Permission denied
+busybox: /data/data/ga.androidterm/bin/head: Permission denied
+busybox: /data/data/ga.androidterm/bin/hexdump: Permission denied
+busybox: /data/data/ga.androidterm/bin/httpd: Permission denied
+busybox: /data/data/ga.androidterm/bin/ifconfig: Permission denied
+busybox: /data/data/ga.androidterm/bin/ifdown: Permission denied
+busybox: /data/data/ga.androidterm/bin/ifup: Permission denied
+busybox: /data/data/ga.androidterm/bin/inotifyd: Permission denied
+busybox: /data/data/ga.androidterm/bin/install: Permission denied
+busybox: /data/data/ga.androidterm/bin/iostat: Permission denied
+busybox: /data/data/ga.androidterm/bin/ip: Permission denied
+busybox: /data/data/ga.androidterm/bin/ipaddr: Permission denied
+busybox: /data/data/ga.androidterm/bin/ipcalc: Permission denied
+busybox: /data/data/ga.androidterm/bin/iplink: Permission denied
+busybox: /data/data/ga.androidterm/bin/iproute: Permission denied
+busybox: /data/data/ga.androidterm/bin/iprule: Permission denied
+busybox: /data/data/ga.androidterm/bin/iptunnel: Permission denied
+busybox: /data/data/ga.androidterm/bin/klogd: Permission denied
+busybox: /data/data/ga.androidterm/bin/ln: Permission denied
+busybox: /data/data/ga.androidterm/bin/loadkmap: Permission denied
+busybox: /data/data/ga.androidterm/bin/losetup: Permission denied
+busybox: /data/data/ga.androidterm/bin/lpd: Permission denied
+busybox: /data/data/ga.androidterm/bin/lpq: Permission denied
+busybox: /data/data/ga.androidterm/bin/lpr: Permission denied
+busybox: /data/data/ga.androidterm/bin/ls: Permission denied
+busybox: /data/data/ga.androidterm/bin/lsattr: Permission denied
+busybox: /data/data/ga.androidterm/bin/lsof: Permission denied
+busybox: /data/data/ga.androidterm/bin/lspci: Permission denied
+busybox: /data/data/ga.androidterm/bin/lsusb: Permission denied
+busybox: /data/data/ga.androidterm/bin/lzcat: Permission denied
+busybox: /data/data/ga.androidterm/bin/lzma: Permission denied
+busybox: /data/data/ga.androidterm/bin/lzop: Permission denied
+busybox: /data/data/ga.androidterm/bin/lzopcat: Permission denied
+busybox: /data/data/ga.androidterm/bin/makedevs: Permission denied
+busybox: /data/data/ga.androidterm/bin/makemime: Permission denied
+busybox: /data/data/ga.androidterm/bin/man: Permission denied
+busybox: /data/data/ga.androidterm/bin/md5sum: Permission denied
+busybox: /data/data/ga.androidterm/bin/mkdir: Permission denied
+busybox: /data/data/ga.androidterm/bin/mkfifo: Permission denied
+busybox: /data/data/ga.androidterm/bin/mknod: Permission denied
+busybox: /data/data/ga.androidterm/bin/mkswap: Permission denied
+busybox: /data/data/ga.androidterm/bin/mktemp: Permission denied
+busybox: /data/data/ga.androidterm/bin/more: Permission denied
+busybox: /data/data/ga.androidterm/bin/mpstat: Permission denied
+busybox: /data/data/ga.androidterm/bin/mv: Permission denied
+busybox: /data/data/ga.androidterm/bin/nbd-client: Permission denied
+busybox: /data/data/ga.androidterm/bin/nc: Permission denied
+busybox: /data/data/ga.androidterm/bin/netstat: Permission denied
+busybox: /data/data/ga.androidterm/bin/nice: Permission denied
+busybox: /data/data/ga.androidterm/bin/nmeter: Permission denied
+busybox: /data/data/ga.androidterm/bin/nohup: Permission denied
+busybox: /data/data/ga.androidterm/bin/od: Permission denied
+busybox: /data/data/ga.androidterm/bin/openvt: Permission denied
+busybox: /data/data/ga.androidterm/bin/patch: Permission denied
+busybox: /data/data/ga.androidterm/bin/pidof: Permission denied
+busybox: /data/data/ga.androidterm/bin/pipe_progress: Permission denied
+busybox: /data/data/ga.androidterm/bin/pmap: Permission denied
+busybox: /data/data/ga.androidterm/bin/popmaildir: Permission denied
+busybox: /data/data/ga.androidterm/bin/printenv: Permission denied
+busybox: /data/data/ga.androidterm/bin/printf: Permission denied
+busybox: /data/data/ga.androidterm/bin/pscan: Permission denied
+busybox: /data/data/ga.androidterm/bin/pstree: Permission denied
+busybox: /data/data/ga.androidterm/bin/pwd: Permission denied
+busybox: /data/data/ga.androidterm/bin/pwdx: Permission denied
+busybox: /data/data/ga.androidterm/bin/raidautorun: Permission denied
+busybox: /data/data/ga.androidterm/bin/rdev: Permission denied
+busybox: /data/data/ga.androidterm/bin/readlink: Permission denied
+busybox: /data/data/ga.androidterm/bin/readprofile: Permission denied
+busybox: /data/data/ga.androidterm/bin/realpath: Permission denied
+busybox: /data/data/ga.androidterm/bin/reformime: Permission denied
+busybox: /data/data/ga.androidterm/bin/renice: Permission denied
+busybox: /data/data/ga.androidterm/bin/reset: Permission denied
+busybox: /data/data/ga.androidterm/bin/resize: Permission denied
+busybox: /data/data/ga.androidterm/bin/rev: Permission denied
+busybox: /data/data/ga.androidterm/bin/rm: Permission denied
+busybox: /data/data/ga.androidterm/bin/rmdir: Permission denied
+busybox: /data/data/ga.androidterm/bin/route: Permission denied
+busybox: /data/data/ga.androidterm/bin/rpm: Permission denied
+busybox: /data/data/ga.androidterm/bin/rpm2cpio: Permission denied
+busybox: /data/data/ga.androidterm/bin/rtcwake: Permission denied
+busybox: /data/data/ga.androidterm/bin/run-parts: Permission denied
+busybox: /data/data/ga.androidterm/bin/runsv: Permission denied
+busybox: /data/data/ga.androidterm/bin/runsvdir: Permission denied
+busybox: /data/data/ga.androidterm/bin/rx: Permission denied
+busybox: /data/data/ga.androidterm/bin/script: Permission denied
+busybox: /data/data/ga.androidterm/bin/scriptreplay: Permission denied
+busybox: /data/data/ga.androidterm/bin/sed: Permission denied
+busybox: /data/data/ga.androidterm/bin/sendmail: Permission denied
+busybox: /data/data/ga.androidterm/bin/seq: Permission denied
+busybox: /data/data/ga.androidterm/bin/setconsole: Permission denied
+busybox: /data/data/ga.androidterm/bin/setkeycodes: Permission denied
+busybox: /data/data/ga.androidterm/bin/setlogcons: Permission denied
+busybox: /data/data/ga.androidterm/bin/setserial: Permission denied
+busybox: /data/data/ga.androidterm/bin/setsid: Permission denied
+busybox: /data/data/ga.androidterm/bin/setuidgid: Permission denied
+busybox: /data/data/ga.androidterm/bin/sh: Permission denied
+busybox: /data/data/ga.androidterm/bin/sha1sum: Permission denied
+busybox: /data/data/ga.androidterm/bin/sha256sum: Permission denied
+busybox: /data/data/ga.androidterm/bin/sha512sum: Permission denied
+busybox: /data/data/ga.androidterm/bin/showkey: Permission denied
+busybox: /data/data/ga.androidterm/bin/sleep: Permission denied
+busybox: /data/data/ga.androidterm/bin/smemcap: Permission denied
+busybox: /data/data/ga.androidterm/bin/softlimit: Permission denied
+busybox: /data/data/ga.androidterm/bin/sort: Permission denied
+busybox: /data/data/ga.androidterm/bin/split: Permission denied
+busybox: /data/data/ga.androidterm/bin/start-stop-daemon: Permission denied
+busybox: /data/data/ga.androidterm/bin/strings: Permission denied
+busybox: /data/data/ga.androidterm/bin/stty: Permission denied
+busybox: /data/data/ga.androidterm/bin/sum: Permission denied
+busybox: /data/data/ga.androidterm/bin/sv: Permission denied
+busybox: /data/data/ga.androidterm/bin/svlogd: Permission denied
+busybox: /data/data/ga.androidterm/bin/sync: Permission denied
+busybox: /data/data/ga.androidterm/bin/sysctl: Permission denied
+busybox: /data/data/ga.androidterm/bin/tac: Permission denied
+busybox: /data/data/ga.androidterm/bin/tail: Permission denied
+busybox: /data/data/ga.androidterm/bin/tar: Permission denied
+busybox: /data/data/ga.androidterm/bin/tcpsvd: Permission denied
+busybox: /data/data/ga.androidterm/bin/tee: Permission denied
+busybox: /data/data/ga.androidterm/bin/test: Permission denied
+busybox: /data/data/ga.androidterm/bin/time: Permission denied
+busybox: /data/data/ga.androidterm/bin/timeout: Permission denied
+busybox: /data/data/ga.androidterm/bin/top: Permission denied
+busybox: /data/data/ga.androidterm/bin/touch: Permission denied
+busybox: /data/data/ga.androidterm/bin/tr: Permission denied
+busybox: /data/data/ga.androidterm/bin/true: Permission denied
+busybox: /data/data/ga.androidterm/bin/ttysize: Permission denied
+busybox: /data/data/ga.androidterm/bin/tunctl: Permission denied
+busybox: /data/data/ga.androidterm/bin/tune2fs: Permission denied
+busybox: /data/data/ga.androidterm/bin/udhcpc: Permission denied
+busybox: /data/data/ga.androidterm/bin/uname: Permission denied
+busybox: /data/data/ga.androidterm/bin/uncompress: Permission denied
+busybox: /data/data/ga.androidterm/bin/unexpand: Permission denied
+busybox: /data/data/ga.androidterm/bin/uniq: Permission denied
+busybox: /data/data/ga.androidterm/bin/unix2dos: Permission denied
+busybox: /data/data/ga.androidterm/bin/unlzma: Permission denied
+busybox: /data/data/ga.androidterm/bin/unlzop: Permission denied
+busybox: /data/data/ga.androidterm/bin/unxz: Permission denied
+busybox: /data/data/ga.androidterm/bin/unzip: Permission denied
+busybox: /data/data/ga.androidterm/bin/uudecode: Permission denied
+busybox: /data/data/ga.androidterm/bin/uuencode: Permission denied
+busybox: /data/data/ga.androidterm/bin/vi: Permission denied
+busybox: /data/data/ga.androidterm/bin/volname: Permission denied
+busybox: /data/data/ga.androidterm/bin/watch: Permission denied
+busybox: /data/data/ga.androidterm/bin/wc: Permission denied
+busybox: /data/data/ga.androidterm/bin/wget: Permission denied
+busybox: /data/data/ga.androidterm/bin/which: Permission denied
+busybox: /data/data/ga.androidterm/bin/whoami: Permission denied
+busybox: /data/data/ga.androidterm/bin/whois: Permission denied
+busybox: /data/data/ga.androidterm/bin/xargs: Permission denied
+busybox: /data/data/ga.androidterm/bin/xz: Permission denied
+busybox: /data/data/ga.androidterm/bin/xzcat: Permission denied
+busybox: /data/data/ga.androidterm/bin/yes: Permission denied
+busybox: /data/data/ga.androidterm/bin/zcat: Permission denied
+tar: can't remove old file ./links/git-shell: Permission denied
+cat: can't open '/data/data/ga.androidterm/links/git': Permission denied
+rm: can't stat '/data/data/ga.androidterm/links/git': Permission denied
+cat: can't open '/data/data/ga.androidterm/links/git-shell': Permission denied
+rm: can't stat '/data/data/ga.androidterm/links/git-shell': Permission denied
+cat: can't open '/data/data/ga.androidterm/links/git-upload-pack': Permission denied
+rm: can't stat '/data/data/ga.androidterm/links/git-upload-pack': Permission denied
+lib/lib.runshell.so: line 133: can't create /data/data/ga.androidterm/runshell: Permission denied
+lib/lib.runshell.so: line 133: can't create /data/data/ga.androidterm/runshell: Permission denied
+chmod: runshell: Operation not permitted
+lib/lib.runshell.so: line 133: can't create /data/data/ga.androidterm/bin/trustedkeys.gpg: Permission denied
+lib/lib.runshell.so: line 133: can't create /data/data/ga.androidterm/installed-version: Permission denied
+Installation complete
+tar: write: Broken pipe
+shell@hammerhead:/sdcard/git-annex.home $ ^D
+shell@hammerhead:/ $
+"""]]
+
+Android is new to me, so it's possible I'm doing something utterly wrong.
diff --git a/doc/bugs/Upload_to_S3_fails_.mdwn b/doc/bugs/Upload_to_S3_fails_.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/Upload_to_S3_fails_.mdwn
@@ -0,0 +1,57 @@
+### Please describe the problem.
+
+Uploading a 21GB file to an S3 special remote fails. It will generally fail somewhere at about 3-15%. I am using the new chunking feature, with chunks set to 25MiB.
+
+### What steps will reproduce the problem?
+
+    $ git annex copy my-big-file.tar.bz --to s3
+    copy my-big-file.tar.bz (gpg) (checking s3...) (to s3...)
+    13%       863.8KB/s 6h0m
+      ErrorClosed
+    failed
+    git-annex: copy: 1 failed
+
+### What version of git-annex are you using? On what operating system?
+
+Running on Arch Linux.
+
+    git-annex version: 5.20140818-g10bf03a
+    build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV Inotify DBus DesktopNotify XMPP DNS Feeds Quvi TDFA CryptoHash
+    key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+    remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier ddar hook external
+    local repository version: 5
+    supported repository version: 5
+    upgrade supported from repository versions: 0 1 2 4
+
+### Please provide any additional information below.
+
+If I fire up the web app and open the log, the end looks like this:
+
+
+[[!format sh """
+...
+
+3%       857.3KB/s 6h46m
+3%       857.3KB/s 6h46m
+3%       857.3KB/s 6h46m
+3%       857.4KB/s 6h46m
+3%       857.4KB/s 6h46m
+3%       857.5KB/s 6h46m
+3%       857.5KB/s 6h46m
+3%       857.6KB/s 6h46m
+3%       857.6KB/s 6h46m
+3%       857.6KB/s 6h46m
+3%       857.7KB/s 6h46m
+3%       857.7KB/s 6h46m
+3%       857.8KB/s 6h46m
+3%       857.8KB/s 6h46m
+3%       857.8KB/s 6h46m
+3%       857.9KB/s 6h46m
+3%       857.9KB/s 6h46m
+3%       858.0KB/s 6h46m
+3%       858.0KB/s 6h46m
+3%       858.1KB/s 6h46m
+3%       858.1KB/s 6h45m
+3%       858.1KB/s 6h45mmux_client_request_session: read from master failed: Broken pipe
+
+"""]]
diff --git a/doc/bugs/Visual_glitch_while_xmpp_pairing.mdwn b/doc/bugs/Visual_glitch_while_xmpp_pairing.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/Visual_glitch_while_xmpp_pairing.mdwn
@@ -0,0 +1,12 @@
+### Please describe the problem.
+When pairing with xmpp buddies, the well does not expand to fit the whole buddy list
+
+### What steps will reproduce the problem?
+Go to the pairing menu
+
+### What version of git-annex are you using? On what operating system?
+ 5.20140717 from the homebrew bottle
+
+### Please provide any additional information below.
+
+![image of bug](http://i.imgur.com/fZe1ERD.png)
diff --git a/doc/bugs/Windows_build_has_hardcoded_paths.mdwn b/doc/bugs/Windows_build_has_hardcoded_paths.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/Windows_build_has_hardcoded_paths.mdwn
@@ -0,0 +1,25 @@
+### Please describe the problem.
+
+The windows build seems to be hardcoded to finding git at c:\program files\Git\
+I have git in another directory. Git-annex does not find it.
+
+### What steps will reproduce the problem?
+
+Install git-annex. Run the webapp.
+Get error "Internal Server Error 
+You need to install git in order to use git-annex!"
+
+### What version of git-annex are you using? On what operating system?
+
+5.20140817-g71c2250.
+Windows XP.
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/__34__old__34___and___34__new__34___hash_formats_are_mixed_up.mdwn b/doc/bugs/__34__old__34___and___34__new__34___hash_formats_are_mixed_up.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/__34__old__34___and___34__new__34___hash_formats_are_mixed_up.mdwn
@@ -0,0 +1,28 @@
+~~~~
+$ git annex version
+git-annex version: 5.20140818-g10bf03a
+~~~~
+
+When repository was initially created, it used "old" hashing from http://git-annex.branchable.com/internals/hashing/ . After some operations, annex was upgraded to "new" format. However, symlinks are still in "old" format and dangling. "git annex fsck", "git annex repair", "git annex pre-commit" - none helps.
+
+~~~~
+$ ls -l pics
+lrwxrwxrwx 1 pfalcon pfalcon 199 Jan 22  2012 IMG_3776.JPG -> ../.git/annex/objects/KM/j6/SHA256E-s688630--5bc2e8beb7a57f6fbcd7d9321cd5283f04448ea475099dac07ae38f002208040.JPG/SHA256E-s688630--5bc2e8beb7a57f6fbcd7d9321cd5283f04448ea475099dac07ae38f002208040.JPG
+lrwxrwxrwx 1 pfalcon pfalcon 199 Jan 22  2012 renamed2.jpg -> ../.git/annex/objects/7F/z3/SHA256E-s676047--3cd28892ee54aba13e074f230709b2c3b87915ff36efd9be3ddfc603e92ecdda.JPG/SHA256E-s676047--3cd28892ee54aba13e074f230709b2c3b87915ff36efd9be3ddfc603e92ecdda.JPG
+lrwxrwxrwx 1 pfalcon pfalcon 199 Jan 22  2012 renamed.jpg -> ../.git/annex/objects/W1/vK/SHA256E-s585398--005fe0534d6cc17a3536c1817b091d00249834c338f289ec6569e9f262889251.JPG/SHA256E-s585398--005fe0534d6cc17a3536c1817b091d00249834c338f289ec6569e9f262889251.JPG
+
+$ find .git/annex/objects/
+.git/annex/objects/
+.git/annex/objects/219
+.git/annex/objects/219/741
+.git/annex/objects/219/741/SHA256E-s585398--005fe0534d6cc17a3536c1817b091d00249834c338f289ec6569e9f262889251.JPG
+.git/annex/objects/219/741/SHA256E-s585398--005fe0534d6cc17a3536c1817b091d00249834c338f289ec6569e9f262889251.JPG/SHA256E-s585398--005fe0534d6cc17a3536c1817b091d00249834c338f289ec6569e9f262889251.JPG
+.git/annex/objects/7a6
+.git/annex/objects/7a6/632
+.git/annex/objects/7a6/632/SHA256E-s688630--5bc2e8beb7a57f6fbcd7d9321cd5283f04448ea475099dac07ae38f002208040.JPG
+.git/annex/objects/7a6/632/SHA256E-s688630--5bc2e8beb7a57f6fbcd7d9321cd5283f04448ea475099dac07ae38f002208040.JPG/SHA256E-s688630--5bc2e8beb7a57f6fbcd7d9321cd5283f04448ea475099dac07ae38f002208040.JPG
+.git/annex/objects/df3
+.git/annex/objects/df3/9a8
+.git/annex/objects/df3/9a8/SHA256E-s676047--3cd28892ee54aba13e074f230709b2c3b87915ff36efd9be3ddfc603e92ecdda.JPG
+.git/annex/objects/df3/9a8/SHA256E-s676047--3cd28892ee54aba13e074f230709b2c3b87915ff36efd9be3ddfc603e92ecdda.JPG/SHA256E-s676047--3cd28892ee54aba13e074f230709b2c3b87915ff36efd9be3ddfc603e92ecdda.JPG
+~~~~
diff --git a/doc/bugs/ssh_over_IPv6.mdwn b/doc/bugs/ssh_over_IPv6.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/ssh_over_IPv6.mdwn
@@ -0,0 +1,20 @@
+### Please describe the problem.
+When i try to sync to my server (path in .git/config is "[fcb8:b10:1cb8:c94:58d0:2522:89f9:c89e]:/home/thomas/git/musik") the url gets messed up by annex and i get the error "git-annex: bad url ssh://[fcb8/~/b10:1cb8:c94:58d0:2522:89f9:c89e]:/home/thomas/git/musik".
+
+### What steps will reproduce the problem?
+1. init git & annex
+2. add files
+3. add a IPv6 address remote
+4. push git branches
+5. git annex sync
+
+### What version of git-annex are you using? On what operating system?
+```
+git-annex version: 5.20140412ubuntu1
+build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV Inotify DBus DesktopNotify XMPP DNS Feeds Quvi TDFA CryptoHash
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+local repository version: 5
+supported repository version: 5
+upgrade supported from repository versions: 0 1 2 4
+```
diff --git a/doc/bugs/ssh_over_IPv6/comment_1_0287f73c44645a1f854ecfe4ddddb258._comment b/doc/bugs/ssh_over_IPv6/comment_1_0287f73c44645a1f854ecfe4ddddb258._comment
new file mode 100644
--- /dev/null
+++ b/doc/bugs/ssh_over_IPv6/comment_1_0287f73c44645a1f854ecfe4ddddb258._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmBUR4O9mofxVbpb8JV9mEbVfIYv670uJo"
+ nickname="Justin"
+ subject="comment 1"
+ date="2014-08-28T20:46:29Z"
+ content="""
+
+Try using ~/.ssh/config as a workaround
+
+    Host myserver
+    Hostname fcb8:b10:1cb8:c94:58d0:2522:89f9:c89e
+
+then just tell git-annex to use myserver
+
+"""]]
diff --git a/doc/bugs/tahoe_remote_has_no_repair.mdwn b/doc/bugs/tahoe_remote_has_no_repair.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/tahoe_remote_has_no_repair.mdwn
@@ -0,0 +1,27 @@
+### Please describe the problem.
+
+The tahoe-lafs remote has no built-in way to perform the repair operation.
+This results to data loss if expiration is enabled on the Tahoe grid.
+
+For the current tahoe-lafs release (1.10.0), the only way storage space is freed
+is via garbage collection. Garbage collection removes shares whose lease has expired.
+Data loss will occur if leases are not periodically renewed via
+"tahoe repair --add-lease WRITECAP".
+
+The current implementation of the Tahoe remote in git-annex does not offer a way to
+run lease renewal, and cannot be used on grids where GC is enabled. (GC is not enabled
+in the default configuration, but on private grids it is a sensible option.)
+
+One way renewal could be made easier to do is to add the uploaded files to a directory
+in Tahoe, so that the leases could be easily updated if the directory writecap is known,
+without needing to go through the full list of writecaps for each file stored.
+
+### What steps will reproduce the problem?
+
+1. Use tahoe remote on a tahoe grid where GC is enabled.
+
+2. After GC expiration period, data loss ensues.
+
+### What version of git-annex are you using? On what operating system?
+
+Seems to affect current git master (as of 2014-08-24).
diff --git a/doc/bugs/vicfg_and_description_often_not_propagated.mdwn b/doc/bugs/vicfg_and_description_often_not_propagated.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/vicfg_and_description_often_not_propagated.mdwn
@@ -0,0 +1,152 @@
+### Please describe the problem.
+
+I can change the settings in one repo and sync it everywhere. Just to be surprised that one repo starts syncing to the transfer, every time it turns out that this repo lost its vicfg settings. Especially the Repository preferred contents are all back on standard. It was even once that it had the current settings and after the change and sync it goes back to some older state instead of the new one.
+
+### What steps will reproduce the problem?
+
+Well that is very hard. I have 8 repos and it happens randomly to some of them. I recreated all of them recently because I thought they are corrupt, that didn't help, just took me one week of time. It is also very hard to find a way to reproduce this because every vicfg causes a merge which takes minutes to hours.
+
+### What version of git-annex are you using? On what operating system?
+
+Linux: git-annex version: 5.20140412ubuntu1
+
+Mac OS: git-annex version: 5.20140717
+
+### Please provide any additional information below.
+
+Layout:
+
+transfer on rsync.net, conntented to that:
+
+ - Two OS X Clients
+
+ - Two Linux Archives
+
+My settings:
+
+
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+# git-annex configuration
+# 
+# Changes saved to this file will be recorded in the git-annex branch.
+# 
+# Lines in this file have the format:
+#   setting field = value
+
+# Repository trust configuration
+# (Valid trust levels: trusted semitrusted untrusted dead)
+# (for Music bei Pirmin)
+trust 0734498b-817c-419f-a0c0-660854dc7cbe = trusted
+# (for Music bei Jean (Willikins) [willikins])
+trust 20e9d2e5-9563-4507-82d5-bf8e23be29a5 = trusted
+# (for Music bei Jean (Willikins Clone))
+trust 6e3431e9-8ec2-404a-9c35-b967db63147d = trusted
+# (for Music bei Jean (Watson))
+trust a6febfa0-9fe5-4a65-95bb-dc255d87c2e2 = trusted
+# (for )
+trust dafe9a64-2480-40e2-9688-9f783577ef72 = dead
+# (for web)
+#trust 00000000-0000-0000-0000-000000000001 = semitrusted
+# (for music transfer via rsync.net [music_rsync])
+#trust 83c42610-42ad-459d-92a4-1aca2dfb97e1 = semitrusted
+
+# Repository groups
+# (Standard groups: client transfer backup incrementalbackup smallarchive archive source manual public unwanted)
+# (Separate group names with spaces)
+# (for Music bei Jean (Willikins) [willikins])
+group 20e9d2e5-9563-4507-82d5-bf8e23be29a5 = archive
+# (for Music bei Jean (Willikins Clone))
+group 6e3431e9-8ec2-404a-9c35-b967db63147d = archive
+# (for )
+group 26d38f31-cb6c-412c-84ef-597d7959a680 = backup
+# (for Music bei Pirmin)
+group 0734498b-817c-419f-a0c0-660854dc7cbe = client
+# (for Music bei Jean (Watson))
+group a6febfa0-9fe5-4a65-95bb-dc255d87c2e2 = client
+# (for music transfer via rsync.net [music_rsync])
+group 83c42610-42ad-459d-92a4-1aca2dfb97e1 = transfer
+# (for )
+group dafe9a64-2480-40e2-9688-9f783577ef72 = unwanted
+# (for web)
+#group 00000000-0000-0000-0000-000000000001 = 
+
+# Repository preferred contents
+# (Set to "standard" to use a repository's group's preferred contents)
+# (for Music bei Jean (Willikins) [willikins])
+wanted 20e9d2e5-9563-4507-82d5-bf8e23be29a5 = (not (copies=archive:2 or copies=smallarchive:2)) or approxlackingcopies=2
+# (for Music bei Jean (Willikins Clone))
+wanted 6e3431e9-8ec2-404a-9c35-b967db63147d = (not (copies=archive:2 or copies=smallarchive:2)) or approxlackingcopies=2
+# (for music transfer via rsync.net [music_rsync])
+wanted 83c42610-42ad-459d-92a4-1aca2dfb97e1 = not (inallgroup=client and copies=archive:2 and copies=client:2) and ((((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or approxlackingcopies=1)
+# (for Music bei Pirmin)
+wanted 0734498b-817c-419f-a0c0-660854dc7cbe = standard
+# (for )
+wanted 26d38f31-cb6c-412c-84ef-597d7959a680 = standard
+# (for )
+wanted dafe9a64-2480-40e2-9688-9f783577ef72 = standard
+# (for web)
+#wanted 00000000-0000-0000-0000-000000000001 = 
+# (for Music bei Jean (Watson))
+wanted a6febfa0-9fe5-4a65-95bb-dc255d87c2e2 = standard
+
+# Group preferred contents
+# (Used by repositories with "groupwanted" in their preferred contents)
+#groupwanted archive = 
+#groupwanted backup = 
+#groupwanted client = 
+#groupwanted incrementalbackup = 
+#groupwanted manual = 
+#groupwanted public = 
+#groupwanted smallarchive = 
+#groupwanted source = 
+#groupwanted transfer = 
+#groupwanted unwanted = 
+
+# Standard preferred contents
+# (Used by wanted or groupwanted expressions containing "standard")
+# (For reference only; built-in and cannot be changed!)
+# standard client = (((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or approxlackingcopies=1
+# standard transfer = (not (inallgroup=client and copies=client:2) and ((((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or approxlackingcopies=1)) or approxlackingcopies=1
+# standard backup = include=* or unused
+# standard incrementalbackup = ((include=* or unused) and (not copies=incrementalbackup:1)) or approxlackingcopies=1
+# standard smallarchive = ((include=*/archive/* or include=archive/*) and ((not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1)) or approxlackingcopies=1
+# standard archive = (not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1
+# standard source = not (copies=1)
+# standard manual = present and ((((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or approxlackingcopies=1)
+# standard public = inpreferreddir
+# standard unwanted = exclude=*
+
+# Repository required contents
+# (for web)
+#required 00000000-0000-0000-0000-000000000001 = 
+# (for Music bei Pirmin)
+#required 0734498b-817c-419f-a0c0-660854dc7cbe = 
+# (for Music bei Jean (Willikins) [willikins])
+#required 20e9d2e5-9563-4507-82d5-bf8e23be29a5 = 
+# (for Music bei Jean (Willikins Clone))
+#required 6e3431e9-8ec2-404a-9c35-b967db63147d = 
+# (for music transfer via rsync.net [music_rsync])
+#required 83c42610-42ad-459d-92a4-1aca2dfb97e1 = 
+# (for Music bei Jean (Watson))
+#required a6febfa0-9fe5-4a65-95bb-dc255d87c2e2 = 
+
+# Scheduled activities
+# (Separate multiple activities with "; ")
+# (for web)
+#schedule 00000000-0000-0000-0000-000000000001 = 
+# (for Music bei Pirmin)
+#schedule 0734498b-817c-419f-a0c0-660854dc7cbe = 
+# (for Music bei Jean (Willikins) [willikins])
+#schedule 20e9d2e5-9563-4507-82d5-bf8e23be29a5 = 
+# (for Music bei Jean (Willikins Clone))
+#schedule 6e3431e9-8ec2-404a-9c35-b967db63147d = 
+# (for music transfer via rsync.net [music_rsync])
+#schedule 83c42610-42ad-459d-92a4-1aca2dfb97e1 = 
+# (for Music bei Jean (Watson))
+#schedule a6febfa0-9fe5-4a65-95bb-dc255d87c2e2 =
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/webapp_missing_on_redhat.mdwn b/doc/bugs/webapp_missing_on_redhat.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/webapp_missing_on_redhat.mdwn
@@ -0,0 +1,14 @@
+### Please describe the problem.
+I am unable to run the webapp on redhat6.5
+
+### What steps will reproduce the problem?
+yum install git-annex 
+
+### What version of git-annex are you using? On what operating system?
+I am using git-annex version  3.20120523 and on redhat 6.5
+
+### Please provide any additional information below.
+I am seeing the following error when running git annex webapp:
+
+git-annex: unknown command webapp
+
diff --git a/doc/bugs/whereis_does_not_work_in_direct_mode.mdwn b/doc/bugs/whereis_does_not_work_in_direct_mode.mdwn
--- a/doc/bugs/whereis_does_not_work_in_direct_mode.mdwn
+++ b/doc/bugs/whereis_does_not_work_in_direct_mode.mdwn
@@ -1,6 +1,6 @@
 ### Please describe the problem.
 
-`git annex whereis` says that there are no copies of any of the files that have been added in repositories running in direct mode.
+`git annex whereis` says that there are no copies of any of the files that have been added in repositories running in direct mode when `annex.alwayscommit` is set to `false`.
 
 In other words, if I add a file from PC1 in direct mode, `whereis` in PC2 will fail. Instead, if I add the same file from PC1 in indirect mode, `whereis` in PC2 will work correctly and will report that the file is present in PC1.
 
@@ -20,7 +20,10 @@
  
 set -e ; set -u
 export LC_ALL=C
- 
+
+# alwayscommit must be set globally to affects whereis and sync
+git config --global annex.alwayscommit false 
+
 direct=true # set to false to make the problem disappear
  
 h=${h:-localhost}
diff --git a/doc/builds.mdwn b/doc/builds.mdwn
--- a/doc/builds.mdwn
+++ b/doc/builds.mdwn
@@ -40,5 +40,8 @@
 <h2>OSX Mavericks</h2>
 <iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks/">
 </iframe>
-<h2>Windows</h2>
+<h2><a href="https://qa.nest-initiative.org/view/msysGit/job/msysgit-git-annex-assistant-test/">Windows</a></h2>
 <a href="https://qa.nest-initiative.org/view/msysGit/job/msysgit-git-annex-assistant-test/">here</a>
+<h2><a href="https://buildd.debian.org/status/package.php?p=git-annex&suite=sid">Debian</a></h2>
+<iframe width=1024 scrolling=no height=500px frameborder=0 marginheight=0 marginwidth=0 src="https://buildd.debian.org/status/package.php?p=git-annex&suite=sid">
+</iframe>
diff --git a/doc/devblog/day_218__scary_locking.mdwn b/doc/devblog/day_218__scary_locking.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/devblog/day_218__scary_locking.mdwn
@@ -0,0 +1,24 @@
+Plan is to be on vacation and/or low activity this week before DebConf.
+However, today I got involved in fixing a bug that caused the assistant to
+keep files open after syncing with repositories on removable media.
+
+Part of that bug involved lock files not being opend close-on-exec, and
+while fixing that I noticed again that the locking code was scattered all
+around and rather repetitive. That led to a lot of refactoring, which is
+always fun when it involves scary locking code. Thanks goodness for
+referential transparency.
+
+Now there's a Utility.LockFile that works on both POSIX and Windows.
+Howver, that module actually exports very different functions for the two.
+While it might be tempting to try to do a portability layer, the
+two locking models are really very different, and there are lots of gotchas
+such a portability layer would face. The only API that's completely the
+same between the two is dropLock.
+
+This refactoring process and the cleaner, more expressive
+code it led to helped me spot a couple of bugs involving locking. See
+[[!commit e386e26ef207db742da6d406183ab851571047ff]]
+and [[!commit 0a4d301051e4933661b7b0a0791afa95bfe9a1d3]]
+Neither bug has ever seemed to cause
+a problem, but it's nice to be able to spot and fix such bugs before they
+do.
diff --git a/doc/download.mdwn b/doc/download.mdwn
--- a/doc/download.mdwn
+++ b/doc/download.mdwn
@@ -26,13 +26,10 @@
   (merge it into master if you need it)
 * `no-bloom` avoids using bloom filters. (merge it into master if you need it)
 * `no-s3` avoids using the S3 library (merge it into master if you need it)
-* `debian-stable` contains the latest backport of git-annex to Debian
-  stable.
+* `debian-*-backport` contains the latest backport of git-annex.
 * `tweak-fetch` adds support for the git tweak-fetch hook, which has
   been proposed and implemented but not yet accepted into git.
 * `setup` contains configuration for this website
-* `pristine-tar` contains [pristine-tar](http://kitenet.net/~joey/code/pristine-tar)
-  data to create tarballs of any past git-annex release.
 
 ----
 
diff --git a/doc/encryption.mdwn b/doc/encryption.mdwn
--- a/doc/encryption.mdwn
+++ b/doc/encryption.mdwn
@@ -17,7 +17,7 @@
 You should decide whether to use encryption with a special remote before
 any data is stored in it. So, `git annex initremote` requires you
 to specify "encryption=none" when first setting up a remote in order
-to disable encryption. To use encryption, you run 
+to disable encryption. To use encryption, you run
 `git-annex initremote` in one of these ways:
 
 * `git annex initremote newremote type=... encryption=hybrid keyid=KEYID ...`
@@ -29,10 +29,10 @@
 The [[hybrid_key_design|design/encryption]] allows additional
 encryption keys to be added on to a special remote later. Due to this
 flexibility, it is the default and recommended encryption scheme.
- 
+
 	git annex initremote newremote type=... [encryption=hybrid] keyid=KEYID ...
 
-Here the KEYID(s) are passed to `gpg` to find encryption keys. 
+Here the KEYID(s) are passed to `gpg` to find encryption keys.
 Typically, you will say "keyid=2512E3C7" to use a specific gpg key.
 Or, you might say "keyid=joey@kitenet.net" to search for matching keys.
 
@@ -58,8 +58,8 @@
 Alternatively, you can configure git-annex to use a shared cipher to
 encrypt data stored in a remote. This shared cipher is stored,
 **unencrypted** in the git repository. So it's shared among every
-clone of the git repository. 
-	
+clone of the git repository.
+
 	git annex initremote newremote type=... encryption=shared
 
 The advantage is you don't need to set up gpg keys. The disadvantage is
@@ -74,10 +74,10 @@
 
 	git annex initremote newremote type=.... encryption=pubkey keyid=KEYID ...
 
-A disavantage is that it is not easy to later add additional public keys
+A disadvantage is that it is not easy to later add additional public keys
 to the special remote. While the `enableremote` parameters `keyid+=` and
 `keyid-=` can be used, they have **no effect** on files that are already
-present on the remote. Probably the only use for these parameters is 
+present on the remote. Probably the only use for these parameters is
 to replace a revoked key:
 
 	git annex enableremote myremote keyid-=2512E3C7 keyid+=788A3F4C
diff --git a/doc/forum/Attempting_to_repair_fails_with_everincreasing_deltas.mdwn b/doc/forum/Attempting_to_repair_fails_with_everincreasing_deltas.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Attempting_to_repair_fails_with_everincreasing_deltas.mdwn
@@ -0,0 +1,21 @@
+Hello,
+
+I am using the latest git-annex with the webui having two local folders (one over nfs) connected as a full backup group. 
+
+On every reboot I get a jumping ball icon with the text:
+
+"Attempting to repair [tr2]"
+
+And the later the text:
+
+"failed to sync to tr2"
+
+The debug log is filled with entries like this, where the number of deltas is increasing:
+
+[2014-08-26 20:34:50 CEST] PushRetrier: Syncing with tr2 
+fatal: pack has 15 unresolved deltas
+error: unpack failed: index-pack abnormal exit
+To /nfs/backup
+ ! [remote rejected] git-annex -> synced/git-annex (n/a (unpacker error))
+ ! [remote rejected] annex/direct/master -> synced/master (n/a (unpacker error))
+error: failed to push some refs to '/nfs/backup''
diff --git a/doc/forum/Using_the_Git-Annex_Assistant_as_a_Backup_and_Syncing_Service.mdwn b/doc/forum/Using_the_Git-Annex_Assistant_as_a_Backup_and_Syncing_Service.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Using_the_Git-Annex_Assistant_as_a_Backup_and_Syncing_Service.mdwn
@@ -0,0 +1,5 @@
+I'm looking to use the Git-Annex Assistant to backup a single repository that is present on and synced between two computers (a home and a working computer). Ideally, each computer uses rsync.net for both of these service, while at the same time treating the cloud storage service as untrusted (so anything stored or tranferred through there is encrypted). Is it possible to do this using solely rsync.net (without the addition of some XMPP service)? According to the software, using shared encryption allows anyone with a clone of the repository to decrypt files on a remote, but the simplest way to make this clone seems to be to first clone to a removable drive, and then from the drive to the second computer (and then deleting the records of the clone to the drive). I'm unsure if by then setting up the backup at rsync.net for the second computer, whether the software will create a second backup that acts independently of the first, neglecting any syncing, or if it will recognize the backup as one of the same repository. I'm also unsure as to whether the software will even sync if the backup is recognized, or whether a tranfer repository at rsync.net is also necessary to complete the setup. Could you perhaps give me some advice on how to achieve this setup, or point me to some information that may help me along?
+
+(If the setup is unclear, I'm essentially trying to replicate something like SpiderOak with the Git-Annex Assistant, without using an XMPP service)
+
+[Edit: It may be easier to just use Git-Annex (no assistant), so that works too]
diff --git a/doc/forum/adding_files_without_hashing_them.mdwn b/doc/forum/adding_files_without_hashing_them.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/adding_files_without_hashing_them.mdwn
@@ -0,0 +1,1 @@
+I would like to be able to add files without having to hash its contents (like WORM) but being able to modify them and record its changes. Is this possible? In other words, I would like to provide other not-that-expensive mechanism for identifying files of a particular version.
diff --git a/doc/forum/difference_between_full_backup_and_number_of_copies__63__.mdwn b/doc/forum/difference_between_full_backup_and_number_of_copies__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/difference_between_full_backup_and_number_of_copies__63__.mdwn
@@ -0,0 +1,9 @@
+If I have three repositories setup in the git annex webui as:
+
+full backup,
+
+and every file put into one of the repos seems to be propagated to the other two,
+
+what is the usage of the setting "number of copies" which is default to 1 but can be increased to 2 or 3? Does this setting matter in this context?
+
+I'm using assistant version 5.20140517.4
diff --git a/doc/forum/git-annex_in_sane_language_for_mere_humans_of_us__63__.mdwn b/doc/forum/git-annex_in_sane_language_for_mere_humans_of_us__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/git-annex_in_sane_language_for_mere_humans_of_us__63__.mdwn
@@ -0,0 +1,1 @@
+So, you provide ARM build. But you probably don't know that my NAS box runs OABI. No, you don't know, you can't know, and you shouldn't know. The only thing worth knowing is that writing great software in obscure and esoteric languages drastically limits its usage, impact, and collaboration around it. So, any idea of writing git-annex implementation in a sane, interpreted, "just works" language, e.g. Python? Thanks.
diff --git a/doc/future_proofing/comment_1_2614eb2e9b7b23fa9bb4251c0d025909._comment b/doc/future_proofing/comment_1_2614eb2e9b7b23fa9bb4251c0d025909._comment
new file mode 100644
--- /dev/null
+++ b/doc/future_proofing/comment_1_2614eb2e9b7b23fa9bb4251c0d025909._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~electrichead"
+ nickname="electrichead"
+ subject="Regarding accessing files in a time capsule..."
+ date="2014-08-25T15:51:00Z"
+ content="""
+Imagine a rather contrived doomsday scenario: the file paths and/or basenames are important and, for some reason, the symlinks are not present (perhaps they got deleted, or aren't supported). `git` and `git-annex` no longer exist and let's assume knowledge of `git` internals is not useful here. All the *content* is there, stored under hashed file names under `.git/annex/objects`.
+
+I may be missing something obvious but I think options for restoring file paths include:
+
+  - direct mode bypasses this issue; all the files are right there. 
+  - the WORM backend perhaps carries enough information in the object file names to work with.
+  - file content/metadata may be sufficient to easily recreate a sensible directory structure in some cases, so no worries.
+
+These first two options may represent compromises in various use-cases and the last may not be applicable or, if it is, practical. The object-path mapping could trivially be backed up in plain text in lieu of these. Like I said, I may be overlooking something here that makes this unnecessary or even a non-concern (actually, I've convinced myself it's not a serious concern in most of the use-cases I've considered, but crossing i's and dotting t's).
+"""]]
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -64,7 +64,7 @@
 
   Adds files in the path to the annex. If no path is specified, adds
   files from the current directory and below.
-  
+
   Files that are already checked into git, or that git has been configured
   to ignore will be silently skipped. (Use `--force` to add ignored files.)
 
@@ -79,6 +79,10 @@
 
   Normally git-annex will choose which repository to copy the content from,
   but you can override this using the `--from` option.
+ 
+  Rather than specifying a filename, the `--all` option can be used to 
+  get all available versions of all files, or the --key=KEY`
+  option can be used to get a specified key.
 
 * `drop [path ...]`
 
@@ -272,10 +276,10 @@
   (Other available variables: feedauthor, itemauthor, itemsummary, itemdescription, itemrights, itemid, itempubdate, title, author)
 
   The `--relaxed` and `--fast` options behave the same as they do in addurl.
-  
+
   When quvi is installed, links in the feed are tested to see if they
   are on a video hosting site, and the video is downloaded. This allows
-  importing eg, youtube playlists.
+  importing e.g., youtube playlists.
 
 * `watch`
 
@@ -319,7 +323,7 @@
   This disables running a local web browser, and outputs the url you
   can use to open the webapp.
 
-  When using the webapp on a remote computer, you'll almost certianly
+  When using the webapp on a remote computer, you'll almost certainly
   want to enable HTTPS. The webapp will use HTTPS if it finds
   a .git/annex/privkey.pem and .git/annex/certificate.pem. Here's
   one way to generate those files, using a self-signed certificate:
@@ -388,7 +392,7 @@
 
   The name of the remote is the same name used when originally
   creating that remote with "initremote". Run "git annex enableremote"
-  with no parameters to get a list of special remote names.
+  without any name to get a list of special remote names.
 
   Some special remotes may need parameters to be specified every time.
   For example, the directory special remote requires a directory= parameter.
@@ -425,7 +429,7 @@
   Run without a number to get the current value.
 
   When git-annex is asked to drop a file, it first verifies that the
-  required number of copies can be satisfied amoung all the other
+  required number of copies can be satisfied among all the other
   repositories that have a copy of the file.
 
   This can be overridden on a per-file basis by the annex.numcopies setting
@@ -645,7 +649,7 @@
   `--format`. The default output format is the same as `--format='${file}\\n'`
 
   These variables are available for use in formats: file, key, backend,
-  bytesize, humansize, keyname, hashdirlower, hashdirmixed, mtime (for 
+  bytesize, humansize, keyname, hashdirlower, hashdirmixed, mtime (for
   the mtime field of a WORM key).
 
 * `whereis [path ...]`
@@ -715,13 +719,13 @@
 
 * `metadata [path ...] [-s field=value -s field+=value -s field-=value ...] [-g field]`
 
-  The content of a file can have any number of metadata fields 
+  The content of a file can have any number of metadata fields
   attached to it to describe it. Each metadata field can in turn
-  have any number of values. 
-  
+  have any number of values.
+
   This command can be used to set metadata, or show the currently set
   metadata.
-  
+
   To show current metadata, run without any -s parameters. The --json
   option will enable json output.
 
@@ -750,7 +754,7 @@
   and checks out the view branch. Only files in the current branch whose
   metadata matches all the specified field values and tags will be
   shown in the view.
-  
+
   Multiple values for a metadata field can be specified, either by using
   a glob (`field="*"`) or by listing each wanted value. The resulting view
   will put files in subdirectories according to the value of their fields.
@@ -785,9 +789,9 @@
   Changes the current view, adding an additional level of directories
   to categorize the files.
 
-  For example, when the view is by author/tag, `vadd year=*` will 
-  change it to year/author/tag. 
-  
+  For example, when the view is by author/tag, `vadd year=*` will
+  change it to year/author/tag.
+
   So will `vadd year=2014 year=2013`, but limiting the years in view
   to only those two.
 
@@ -934,7 +938,7 @@
 * `findref [ref]`
 
   This is similar to the find command, but instead of finding files in the
-  current work tree, it finds files in the specified git ref. 
+  current work tree, it finds files in the specified git ref.
 
   Most MATCHING OPTIONS can be used with findref, to limit the files it
   finds. However, the --include and --exclude options will not work.
@@ -1125,7 +1129,7 @@
   Caused a desktop notification to be displayed after each successful
   file download and upload.
 
-  (Only supported on some platforms, eg Linux with dbus. A no-op when
+  (Only supported on some platforms, e.g. Linux with dbus. A no-op when
   not supported.)
 
 * `--notify-start`
@@ -1316,7 +1320,7 @@
 connected.
 
 The scheduled jobs can be configured using `git annex vicfg` or
-`git annex schedule`. 
+`git annex schedule`.
 
 These actions are available: "fsck self", "fsck UUID" (where UUID
 is the UUID of a remote to fsck). After the action comes the duration
@@ -1372,7 +1376,7 @@
 
   This is a deprecated setting. You should instead use the
   `git annex numcopies` command to configure how many copies of files
-  are kept acros all repositories.
+  are kept across all repositories.
 
   This config setting is only looked at when `git annex numcopies` has
   never been configured.
@@ -1382,8 +1386,8 @@
 * `annex.genmetadata`
 
   Set this to `true` to make git-annex automatically generate some metadata
-  when adding files to the repository. 
-  
+  when adding files to the repository.
+
   In particular, it stores year and month metadata, from the file's
   modification date.
 
@@ -1424,7 +1428,7 @@
 
   By default, git-annex automatically commits data to the git-annex branch
   after each command is run. If you have a series
-  of commands that you want to make a single commit, you can 
+  of commands that you want to make a single commit, you can
   run the commands with `-c annex.alwayscommit=false`. You can later
   commit the data by running `git annex merge` (or by automatic merges)
   or `git annex sync`.
@@ -1441,7 +1445,7 @@
 
   Controls what the assistant does about unused file contents
   that are stored in the repository.
-  
+
   The default is `false`, which causes
   all old and unused file contents to be retained, unless the assistant
   is able to move them to some other repository (such as a backup repository).
@@ -1611,7 +1615,7 @@
 
   These options are passed after other applicable rsync options,
   so can be used to override them. For example, to limit upload bandwidth
-  to 10Kbye/s, set `--bwlimit 10`.
+  to 10Kbyte/s, set `--bwlimit 10`.
 
 * `remote.<name>.annex-rsync-download-options`
 
@@ -1686,7 +1690,7 @@
   In the command line, %file is replaced with the file that should be
   erased.
 
-  For example, to use the wipe command, set it to `wipe -f %file`
+  For example, to use the wipe command, set it to `wipe -f %file`.
 
 * `remote.<name>.rsyncurl`
 
@@ -1781,7 +1785,7 @@
 
 Also note that when using views, only the toplevel .gitattributes file is
 preserved in the view, so other settings in other files won't have any
-efffect.
+effect.
 
 # FILES
 
diff --git a/doc/install/cabal/comment_39_a86057d7e6d47113330f79e1812c3a5d._comment b/doc/install/cabal/comment_39_a86057d7e6d47113330f79e1812c3a5d._comment
new file mode 100644
--- /dev/null
+++ b/doc/install/cabal/comment_39_a86057d7e6d47113330f79e1812c3a5d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkftzaCvV7EDKVDfJhsQZ3E1Vn-0db516w"
+ nickname="Edward"
+ subject="GHC 7.8 Issue"
+ date="2014-08-20T20:06:01Z"
+ content="""
+Just an FYI: I tried to \"cabal install --only-dependencies\" with GHC 7.8 and it fails because DAV-1.0.1 is pulling in lens-3.10.3 which is not compatible with GHC 7.8 due to changes in Typeable. 
+
+I don't have enough experience with cabal to figure out why it's not trying to use a newer version of lens.
+"""]]
diff --git a/doc/install/fromscratch/comment_4_765334858ef1eedff2c5d89ed42aa7f6._comment b/doc/install/fromscratch/comment_4_765334858ef1eedff2c5d89ed42aa7f6._comment
new file mode 100644
--- /dev/null
+++ b/doc/install/fromscratch/comment_4_765334858ef1eedff2c5d89ed42aa7f6._comment
@@ -0,0 +1,37 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawld54zdyk6b0W4jXnssSO_j2Nn3W1uVsUE"
+ nickname="Paul"
+ subject="comment 4"
+ date="2014-08-24T11:53:11Z"
+ content="""
+@azul, thanks for hints, but it still fails. No wonders though - this is Haskell, kids.
+
+~~~~
+$ cabal install git-annex --only-dependencies
+Resolving dependencies...
+cabal: Could not resolve dependencies:
+trying: git-annex-5.20140817
+trying: git-annex-5.20140817:+webapp
+trying: git-annex-5.20140817:+s3
+trying: git-annex-5.20140817:+dns
+trying: dns-1.4.3
+trying: yesod-1.2.6.1
+trying: yesod-auth-1.3.4.2
+trying: http-client-0.3.7.1
+trying: http-client-0.3.7.1:+network-uri
+trying: hS3-0.5.8
+trying: hxt-9.3.1.6
+trying: hxt-9.3.1.6:-network-uri
+rejecting: network-2.6.0.1, 2.6.0.0 (conflict: hxt-9.3.1.6:network-uri =>
+network>=2.4 && <2.6)
+rejecting: network-2.5.0.0, 2.4.2.3, 2.4.2.2, 2.4.2.1, 2.4.2.0, 2.4.1.2,
+2.4.1.1, 2.4.1.0, 2.4.0.1, 2.4.0.0, 2.3.2.0, 2.3.1.1, 2.3.1.0, 2.3.0.14,
+2.3.0.13, 2.3.0.12, 2.3.0.11, 2.3.0.10, 2.3.0.9, 2.3.0.8, 2.3.0.7, 2.3.0.6,
+2.3.0.5, 2.3.0.4, 2.3.0.3, 2.3.0.2, 2.3.0.1, 2.3 (conflict:
+http-client-0.3.7.1:network-uri => network>=2.6)
+rejecting: network-2.2.3.1, 2.2.3, 2.2.1.10, 2.2.1.9, 2.2.1.8, 2.2.1.7,
+2.2.1.6, 2.2.1.5, 2.2.1.4, 2.2.1.3, 2.2.1.2, 2.2.1.1, 2.2.1, 2.2.0.1, 2.2.0.0,
+2.1.0.0, 2.0 (conflict: dns => network>=2.3)
+~~~~
+
+"""]]
diff --git a/doc/news/version_5.20140613.mdwn b/doc/news/version_5.20140613.mdwn
deleted file mode 100644
--- a/doc/news/version_5.20140613.mdwn
+++ /dev/null
@@ -1,16 +0,0 @@
-git-annex 5.20140613 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Ignore setsid failures.
-   * Avoid leaving behind .tmp files when failing in some cases, including
-     importing files to a disk that is full.
-   * Avoid bad commits after interrupted direct mode sync (or merge).
-   * Fix build with wai 0.3.0.
-   * Deal with FAT's low resolution timestamps, which in combination with
-     Linux's caching of higher res timestamps while a FAT is mounted, caused
-     direct mode repositories on FAT to seem to have modified files after
-     they were unmounted and remounted.
-   * Windows: Fix opening webapp when repository is in a directory with
-     spaces in the path.
-   * Detect when Windows has lost its mind in a timezone change, and
-     automatically apply a delta to the timestamps it returns, to get back to
-     sane values."""]]
diff --git a/doc/news/version_5.20140831.mdwn b/doc/news/version_5.20140831.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/news/version_5.20140831.mdwn
@@ -0,0 +1,13 @@
+git-annex 5.20140831 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Make --help work when not in a git repository. Closes: #[758592](http://bugs.debian.org/758592)
+   * Ensure that all lock fds are close-on-exec, fixing various problems with
+     them being inherited by child processes such as git commands.
+   * When accessing a local remote, shut down git-cat-file processes
+     afterwards, to ensure that remotes on removable media can be unmounted.
+     Closes: #[758630](http://bugs.debian.org/758630)
+   * Fix handing of autocorrection when running outside a git repository.
+   * Fix stub git-annex test support when built without tasty.
+   * Do not preserve permissions and acls when copying files from
+     one local git repository to another. Timestamps are still preserved
+     as long as cp --preserve=timestamps is supported. Closes: #[729757](http://bugs.debian.org/729757)"""]]
diff --git a/doc/todo/merge_in_ram___40__disk__41____63__.mdwn b/doc/todo/merge_in_ram___40__disk__41____63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/todo/merge_in_ram___40__disk__41____63__.mdwn
@@ -0,0 +1,5 @@
+git-annex is great. But for my repos the merge and recording state operations take forever.
+
+(merging fotos_enc_pg/synced/git-annex into git-annex...)
+
+Since git-annex is another branch (than master) and git usually needs a worktree for merging I assume that git-annex branch is temporarily checked out somewhere. Would it be possible to move this operation to RAM? Or a RAM-Disk?
diff --git a/git-annex.1 b/git-annex.1
--- a/git-annex.1
+++ b/git-annex.1
@@ -74,6 +74,10 @@
 Normally git\-annex will choose which repository to copy the content from,
 but you can override this using the \fB\-\-from\fP option.
 .IP
+Rather than specifying a filename, the \fB\-\-all\fP option can be used to 
+get all available versions of all files, or the \-\-key=KEY
+option can be used to get a specified key.
+.IP
 .IP "\fBdrop [path ...]\fP"
 Drops the content of annexed files from this repository.
 .IP
@@ -255,7 +259,7 @@
 .IP
 When quvi is installed, links in the feed are tested to see if they
 are on a video hosting site, and the video is downloaded. This allows
-importing eg, youtube playlists.
+importing e.g., youtube playlists.
 .IP
 .IP "\fBwatch\fP"
 Watches for changes to files in the current directory and its subdirectories,
@@ -296,7 +300,7 @@
 This disables running a local web browser, and outputs the url you
 can use to open the webapp.
 .IP
-When using the webapp on a remote computer, you'll almost certianly
+When using the webapp on a remote computer, you'll almost certainly
 want to enable HTTPS. The webapp will use HTTPS if it finds
 a .git/annex/privkey.pem and .git/annex/certificate.pem. Here's
 one way to generate those files, using a self\-signed certificate:
@@ -361,7 +365,7 @@
 .IP
 The name of the remote is the same name used when originally
 creating that remote with "initremote". Run "git annex enableremote"
-with no parameters to get a list of special remote names.
+without any name to get a list of special remote names.
 .IP
 Some special remotes may need parameters to be specified every time.
 For example, the directory special remote requires a directory= parameter.
@@ -397,7 +401,7 @@
 Run without a number to get the current value.
 .IP
 When git\-annex is asked to drop a file, it first verifies that the
-required number of copies can be satisfied amoung all the other
+required number of copies can be satisfied among all the other
 repositories that have a copy of the file.
 .IP
 This can be overridden on a per\-file basis by the annex.numcopies setting
@@ -597,7 +601,7 @@
 \fB\-\-format\fP. The default output format is the same as \fB\-\-format='${file}\\n'\fP
 .IP
 These variables are available for use in formats: file, key, backend,
-bytesize, humansize, keyname, hashdirlower, hashdirmixed, mtime (for 
+bytesize, humansize, keyname, hashdirlower, hashdirmixed, mtime (for
 the mtime field of a WORM key).
 .IP
 .IP "\fBwhereis [path ...]\fP"
@@ -660,9 +664,9 @@
 .SH METADATA COMMANDS
 .IP "\fBmetadata [path ...] [\-s field=value \-s field+=value \-s field\-=value ...] [\-g field]\fP"
 .IP
-The content of a file can have any number of metadata fields 
+The content of a file can have any number of metadata fields
 attached to it to describe it. Each metadata field can in turn
-have any number of values. 
+have any number of values.
 .IP
 This command can be used to set metadata, or show the currently set
 metadata.
@@ -726,8 +730,8 @@
 Changes the current view, adding an additional level of directories
 to categorize the files.
 .IP
-For example, when the view is by author/tag, \fBvadd year=*\fP will 
-change it to year/author/tag. 
+For example, when the view is by author/tag, \fBvadd year=*\fP will
+change it to year/author/tag.
 .IP
 So will \fBvadd year=2014 year=2013\fP, but limiting the years in view
 to only those two.
@@ -860,7 +864,7 @@
 .IP
 .IP "\fBfindref [ref]\fP"
 This is similar to the find command, but instead of finding files in the
-current work tree, it finds files in the specified git ref. 
+current work tree, it finds files in the specified git ref.
 .IP
 Most MATCHING OPTIONS can be used with findref, to limit the files it
 finds. However, the \-\-include and \-\-exclude options will not work.
@@ -1024,7 +1028,7 @@
 Caused a desktop notification to be displayed after each successful
 file download and upload.
 .IP
-(Only supported on some platforms, eg Linux with dbus. A no\-op when
+(Only supported on some platforms, e.g. Linux with dbus. A no\-op when
 not supported.)
 .IP
 .IP "\fB\-\-notify\-start\fP"
@@ -1190,7 +1194,7 @@
 connected.
 .PP
 The scheduled jobs can be configured using \fBgit annex vicfg\fP or
-\fBgit annex schedule\fP. 
+\fBgit annex schedule\fP.
 .PP
 These actions are available: "fsck self", "fsck UUID" (where UUID
 is the UUID of a remote to fsck). After the action comes the duration
@@ -1240,7 +1244,7 @@
 .IP "\fBannex.numcopies\fP"
 This is a deprecated setting. You should instead use the
 \fBgit annex numcopies\fP command to configure how many copies of files
-are kept acros all repositories.
+are kept across all repositories.
 .IP
 This config setting is only looked at when \fBgit annex numcopies\fP has
 never been configured.
@@ -1249,7 +1253,7 @@
 .IP
 .IP "\fBannex.genmetadata\fP"
 Set this to \fBtrue\fP to make git\-annex automatically generate some metadata
-when adding files to the repository. 
+when adding files to the repository.
 .IP
 In particular, it stores year and month metadata, from the file's
 modification date.
@@ -1286,7 +1290,7 @@
 .IP "\fBannex.alwayscommit\fP"
 By default, git\-annex automatically commits data to the git\-annex branch
 after each command is run. If you have a series
-of commands that you want to make a single commit, you can 
+of commands that you want to make a single commit, you can
 run the commands with \fB\-c annex.alwayscommit=false\fP. You can later
 commit the data by running \fBgit annex merge\fP (or by automatic merges)
 or \fBgit annex sync\fP.
@@ -1446,7 +1450,7 @@
 .IP
 These options are passed after other applicable rsync options,
 so can be used to override them. For example, to limit upload bandwidth
-to 10Kbye/s, set \fB\-\-bwlimit 10\fP.
+to 10Kbyte/s, set \fB\-\-bwlimit 10\fP.
 .IP
 .IP "\fBremote.<name>.annex\-rsync\-download\-options\fP"
 Options to use when using rsync to download a file from a remote.
@@ -1511,7 +1515,7 @@
 In the command line, %file is replaced with the file that should be
 erased.
 .IP
-For example, to use the wipe command, set it to \fBwipe \-f %file\fP
+For example, to use the wipe command, set it to \fBwipe \-f %file\fP.
 .IP
 .IP "\fBremote.<name>.rsyncurl\fP"
 Used by rsync special remotes, this configures
@@ -1594,7 +1598,7 @@
 .PP
 Also note that when using views, only the toplevel .gitattributes file is
 preserved in the view, so other settings in other files won't have any
-efffect.
+effect.
 .PP
 .SH FILES
 These files are used by git\-annex:
diff --git a/git-annex.cabal b/git-annex.cabal
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
 Name: git-annex
-Version: 5.20140817
+Version: 5.20140831
 Cabal-Version: >= 1.8
 License: GPL-3
 Maintainer: Joey Hess <joey@kitenet.net>
@@ -97,7 +97,7 @@
   Build-Depends: MissingH, hslogger, directory, filepath,
    containers, utf8-string, network (>= 2.0), mtl (>= 2),
    bytestring, old-locale, time, dataenc, SHA, process, json,
-   base (>= 4.5 && < 4.9), monad-control, exceptions (>= 0.5), transformers,
+   base (>= 4.5 && < 4.9), monad-control, exceptions (>= 0.6), transformers,
    IfElse, text, QuickCheck >= 2.1, bloomfilter, edit-distance, process,
    SafeSemaphore, uuid, random, dlist, unix-compat, async, stm (>= 2.3),
    data-default, case-insensitive, http-conduit, http-types
