diff --git a/Annex/Branch.hs b/Annex/Branch.hs
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -454,7 +454,7 @@
 			ignoreRefs untransitionedrefs
 			return True
   where
-  	getreftransition ref = do
+	getreftransition ref = do
 		ts <- parseTransitionsStrictly "remote" . decodeBS
 			<$> catFile ref transitionsLog
 		return (ref, ts)
@@ -470,7 +470,7 @@
 getIgnoredRefs :: Annex (S.Set Git.Ref)
 getIgnoredRefs = S.fromList . mapMaybe Git.Sha.extractSha . lines <$> content
   where
-  	content = do
+	content = do
 		f <- fromRepo gitAnnexIgnoredRefs
 		liftIO $ catchDefaultIO "" $ readFile f
 
@@ -498,7 +498,7 @@
 				ref <- getBranch
 				commitIndex jl ref message (nub $ fullname:transitionedrefs)
   where
-  	message
+	message
 		| neednewlocalbranch && null transitionedrefs = "new branch for transition " ++ tdesc
 		| otherwise = "continuing transition " ++ tdesc
 	tdesc = show $ map describeTransition $ transitionList ts
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -100,10 +100,10 @@
 catLink :: Bool -> Sha -> Annex String
 catLink modeguaranteed sha = fromInternalGitPath . decodeBS <$> get
   where
-  	-- If the mode is not guaranteed to be correct, avoid
+	-- If the mode is not guaranteed to be correct, avoid
 	-- buffering the whole file content, which might be large.
 	-- 8192 is enough if it really is a symlink.
-  	get
+	get
 		| modeguaranteed = catObject sha
 		| otherwise = L.take 8192 <$> catObject sha
 
@@ -120,7 +120,7 @@
 catKeyChecked needhead ref@(Ref r) =
 	catKey' False ref =<< findmode <$> catTree treeref
   where
-  	pathparts = split "/" r
+	pathparts = split "/" r
 	dir = intercalate "/" $ take (length pathparts - 1) pathparts
 	file = fromMaybe "" $ lastMaybe pathparts
 	treeref = Ref $ if needhead then "HEAD" ++ dir ++ "/" else dir ++ "/"
diff --git a/Annex/CheckIgnore.hs b/Annex/CheckIgnore.hs
--- a/Annex/CheckIgnore.hs
+++ b/Annex/CheckIgnore.hs
@@ -18,7 +18,7 @@
 checkIgnored :: FilePath -> Annex Bool
 checkIgnored file = go =<< checkIgnoreHandle
   where
-  	go Nothing = return False
+	go Nothing = return False
 	go (Just h) = liftIO $ Git.checkIgnored h file
 
 checkIgnoreHandle :: Annex (Maybe Git.CheckIgnoreHandle)
diff --git a/Annex/Content.hs b/Annex/Content.hs
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -456,7 +456,7 @@
 secureErase :: FilePath -> Annex ()
 secureErase file = maybe noop go =<< annexSecureEraseCommand <$> Annex.getGitConfig
   where
-  	go basecmd = void $ liftIO $
+	go basecmd = void $ liftIO $
 		boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
 	gencmd = massReplace [ ("%file", shellEscape file) ]
 
@@ -555,7 +555,7 @@
 downloadUrl :: [Url.URLString] -> FilePath -> Annex Bool
 downloadUrl urls file = go =<< annexWebDownloadCommand <$> Annex.getGitConfig
   where
-  	go Nothing = Url.withUrlOptions $ \uo ->
+	go Nothing = Url.withUrlOptions $ \uo ->
 		anyM (\u -> Url.download u file uo) urls
 	go (Just basecmd) = liftIO $ anyM (downloadcmd basecmd) urls
 	downloadcmd basecmd url =
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
--- a/Annex/Direct.hs
+++ b/Annex/Direct.hs
@@ -347,7 +347,7 @@
 				(dloc:_) -> return $ Just $ fromdirect dloc
 		)
   where
-  	fromindirect loc = do
+	fromindirect loc = do
 		{- Move content from annex to direct file. -}
 		updateInodeCache k loc
 		void $ addAssociatedFile k f
diff --git a/Annex/Environment.hs b/Annex/Environment.hs
--- a/Annex/Environment.hs
+++ b/Annex/Environment.hs
@@ -45,7 +45,7 @@
 		ensureEnv "GIT_COMMITTER_NAME" username
   where
 #ifndef __ANDROID__
-  	-- existing environment is not overwritten
+	-- existing environment is not overwritten
 	ensureEnv var val = void $ setEnv var val False
 #else
 	-- Environment setting is broken on Android, so this is dealt with
@@ -59,7 +59,7 @@
 ensureCommit :: Annex a -> Annex a
 ensureCommit a = either retry return =<< tryNonAsync a 
   where
-  	retry _ = do
+	retry _ = do
 		name <- liftIO myUserName
 		setConfig (ConfigKey "user.name") name
 		setConfig (ConfigKey "user.email") name
diff --git a/Annex/FileMatcher.hs b/Annex/FileMatcher.hs
--- a/Annex/FileMatcher.hs
+++ b/Annex/FileMatcher.hs
@@ -106,7 +106,7 @@
 largeFilesMatcher :: Annex (FileMatcher Annex)
 largeFilesMatcher = go =<< annexLargeFiles <$> Annex.getGitConfig
   where
-  	go Nothing = return matchAll
+	go Nothing = return matchAll
 	go (Just expr) = do
 		gm <- groupMap
 		rc <- readRemoteLog
diff --git a/Annex/ReplaceFile.hs b/Annex/ReplaceFile.hs
--- a/Annex/ReplaceFile.hs
+++ b/Annex/ReplaceFile.hs
@@ -33,7 +33,7 @@
 	tmpfile <- liftIO $ setup tmpdir
 	go tmpfile `catchNonAsync` (const $ rollback tmpfile)
   where
-  	setup tmpdir = do
+	setup tmpdir = do
 		(tmpfile, h) <- openTempFileWithDefaultPermissions tmpdir "tmp"
 		hClose h
 		return tmpfile
diff --git a/Annex/Ssh.hs b/Annex/Ssh.hs
--- a/Annex/Ssh.hs
+++ b/Annex/Ssh.hs
@@ -78,10 +78,10 @@
 			then Just socketfile
 			else Nothing
   where
-  	-- ssh appends a 16 char extension to the socket when setting it
+	-- ssh appends a 16 char extension to the socket when setting it
 	-- up, which needs to be taken into account when checking
 	-- that a valid socket was constructed.
-  	sshgarbage = replicate (1+16) 'X'
+	sshgarbage = replicate (1+16) 'X'
 
 sshConnectionCachingParams :: FilePath -> [CommandParam]
 sshConnectionCachingParams socketfile = 
diff --git a/Annex/TaggedPush.hs b/Annex/TaggedPush.hs
--- a/Annex/TaggedPush.hs
+++ b/Annex/TaggedPush.hs
@@ -49,13 +49,13 @@
 
 taggedPush :: UUID -> Maybe String -> Git.Ref -> Remote -> Git.Repo -> IO Bool
 taggedPush u info branch remote = Git.Command.runBool
-        [ Param "push"
-        , Param $ Remote.name remote
+	[ Param "push"
+	, Param $ Remote.name remote
 	{- Using forcePush here is safe because we "own" the tagged branch
 	 - we're pushing; it has no other writers. Ensures it is pushed
 	 - even if it has been rewritten by a transition. -}
-        , Param $ Git.Branch.forcePush $ refspec Annex.Branch.name
-        , Param $ refspec branch
-        ]
+	, Param $ Git.Branch.forcePush $ refspec Annex.Branch.name
+	, Param $ refspec branch
+	]
   where
 	refspec b = Git.fromRef b ++ ":" ++ Git.fromRef (toTaggedBranch u info b)
diff --git a/Annex/Transfer.hs b/Annex/Transfer.hs
--- a/Annex/Transfer.hs
+++ b/Annex/Transfer.hs
@@ -69,7 +69,7 @@
 			return False
 		else do
 			ok <- retry info metervar $
-		 		bracketIO (return fd) (cleanup tfile) (const $ a meter)
+				bracketIO (return fd) (cleanup tfile) (const $ a meter)
 			unless ok $ recordFailedTransfer t info
 			return ok
   where
diff --git a/Annex/View.hs b/Annex/View.hs
--- a/Annex/View.hs
+++ b/Annex/View.hs
@@ -102,7 +102,7 @@
 			let (components', viewchanges) = runWriter $
 				mapM (\c -> updateViewComponent c field vf) (viewComponents view)
 			    viewchange = if field `elem` map viewField (viewComponents origview)
-			    	then maximum viewchanges
+				then maximum viewchanges
 				else Narrowing
 			in (view { viewComponents = components' }, viewchange)
 		| otherwise = 
@@ -207,7 +207,7 @@
 viewComponentMatcher viewcomponent = \metadata -> 
 	matcher (currentMetaDataValues metafield metadata)
   where
-  	metafield = viewField viewcomponent
+	metafield = viewField viewcomponent
 	matcher = case viewFilter viewcomponent of
 		FilterValues s -> \values -> setmatches $
 			S.intersection s values
@@ -236,8 +236,8 @@
 fromViewPath :: FilePath -> MetaValue
 fromViewPath = toMetaValue . deescapeslash []
   where
-  	deescapeslash s [] = reverse s
-  	deescapeslash s (c:cs)
+	deescapeslash s [] = reverse s
+	deescapeslash s (c:cs)
 		| c == pseudoSlash = case cs of
 			(c':cs')
 				| c' == pseudoSlash -> deescapeslash (pseudoSlash:s) cs'
diff --git a/Annex/View/ViewedFile.hs b/Annex/View/ViewedFile.hs
--- a/Annex/View/ViewedFile.hs
+++ b/Annex/View/ViewedFile.hs
@@ -58,7 +58,7 @@
 dirFromViewedFile :: ViewedFile -> FilePath
 dirFromViewedFile = joinPath . drop 1 . sep [] ""
   where
-  	sep l _ [] = reverse l
+	sep l _ [] = reverse l
 	sep l curr (c:cs)
 		| c == '%' = sep (reverse curr:l) "" cs
 		| c == '\\' = case cs of
diff --git a/Assistant.hs b/Assistant.hs
--- a/Assistant.hs
+++ b/Assistant.hs
@@ -119,7 +119,7 @@
 			)
 #endif
   where
-  	desc
+	desc
 		| assistant = "assistant"
 		| otherwise = "watch"
 	start daemonize webappwaiter = withThreadState $ \st -> do
@@ -147,7 +147,7 @@
 		let threads = if isJust cannotrun
 			then webappthread
 			else webappthread ++
-				[ watch $ commitThread
+				[ watch commitThread
 #ifdef WITH_WEBAPP
 #ifdef WITH_PAIRING
 				, assist $ pairListenerThread urlrenderer
@@ -158,29 +158,29 @@
 				, assist $ xmppReceivePackThread urlrenderer
 #endif
 #endif
-				, assist $ pushThread
-				, assist $ pushRetryThread
-				, assist $ mergeThread
-				, assist $ transferWatcherThread
-				, assist $ transferPollerThread
-				, assist $ transfererThread
-				, assist $ remoteControlThread
-				, assist $ daemonStatusThread
+				, assist pushThread
+				, assist pushRetryThread
+				, assist mergeThread
+				, assist transferWatcherThread
+				, assist transferPollerThread
+				, assist transfererThread
+				, assist remoteControlThread
+				, assist daemonStatusThread
 				, assist $ sanityCheckerDailyThread urlrenderer
-				, assist $ sanityCheckerHourlyThread
+				, assist sanityCheckerHourlyThread
 				, assist $ problemFixerThread urlrenderer
 #ifdef WITH_CLIBS
 				, assist $ mountWatcherThread urlrenderer
 #endif
-				, assist $ netWatcherThread
+				, assist netWatcherThread
 				, assist $ upgraderThread urlrenderer
 				, assist $ upgradeWatcherThread urlrenderer
-				, assist $ netWatcherFallbackThread
+				, assist netWatcherFallbackThread
 				, assist $ transferScannerThread urlrenderer
 				, assist $ cronnerThread urlrenderer
-				, assist $ configMonitorThread
-				, assist $ glacierThread
-				, watch $ watchThread
+				, assist configMonitorThread
+				, assist glacierThread
+				, watch watchThread
 				-- must come last so that all threads that wait
 				-- on it have already started waiting
 				, watch $ sanityCheckerStartupThread startdelay
diff --git a/Assistant/Alert.hs b/Assistant/Alert.hs
--- a/Assistant/Alert.hs
+++ b/Assistant/Alert.hs
@@ -145,7 +145,7 @@
 		, alertHeader = Just $ tenseWords msg
 		}
   where
-  	msg
+	msg
 		| null succeeded = ["Failed to sync with", showRemotes failed]
 		| null failed = ["Synced with", showRemotes succeeded]
 		| otherwise =
diff --git a/Assistant/Alert/Utility.hs b/Assistant/Alert/Utility.hs
--- a/Assistant/Alert/Utility.hs
+++ b/Assistant/Alert/Utility.hs
@@ -119,7 +119,7 @@
 	  where
 		bloat = M.size m' - maxAlerts
 		pruneold l =
-	 		let (f, rest) = partition (\(_, a) -> isFiller a) l
+			let (f, rest) = partition (\(_, a) -> isFiller a) l
 			in drop bloat f ++ rest
 	updatePrune = pruneBloat $ M.filterWithKey pruneSame $
 		M.insertWith' const i al m
diff --git a/Assistant/DaemonStatus.hs b/Assistant/DaemonStatus.hs
--- a/Assistant/DaemonStatus.hs
+++ b/Assistant/DaemonStatus.hs
@@ -65,7 +65,7 @@
 		, syncingToCloudRemote = any iscloud syncdata
 		}
   where
-  	iscloud r = not (Remote.readonly r) && Remote.availability r == Remote.GloballyAvailable
+	iscloud r = not (Remote.readonly r) && Remote.availability r == Remote.GloballyAvailable
 
 {- Updates the syncRemotes list from the list of all remotes in Annex state. -}
 updateSyncRemotes :: Assistant ()
diff --git a/Assistant/DeleteRemote.hs b/Assistant/DeleteRemote.hs
--- a/Assistant/DeleteRemote.hs
+++ b/Assistant/DeleteRemote.hs
@@ -62,7 +62,7 @@
 				<$> liftAnnex (Remote.remoteFromUUID uuid)
 			mapM_ (queueremaining r) keys
   where
-  	queueremaining r k = 
+	queueremaining r k = 
 		queueTransferWhenSmall "remaining object in unwanted remote"
 			Nothing (Transfer Download uuid k) r
 	{- Scanning for keys can take a long time; do not tie up
diff --git a/Assistant/Gpg.hs b/Assistant/Gpg.hs
--- a/Assistant/Gpg.hs
+++ b/Assistant/Gpg.hs
@@ -20,7 +20,7 @@
 newUserId = do
 	oldkeys <- secretKeys
 	username <- myUserName
-  	let basekeyname = username ++ "'s git-annex encryption key"
+	let basekeyname = username ++ "'s git-annex encryption key"
 	return $ Prelude.head $ filter (\n -> M.null $ M.filter (== n) oldkeys)
 		( basekeyname
 		: map (\n -> basekeyname ++ show n) ([2..] :: [Int])
diff --git a/Assistant/MakeRemote.hs b/Assistant/MakeRemote.hs
--- a/Assistant/MakeRemote.hs
+++ b/Assistant/MakeRemote.hs
@@ -48,7 +48,7 @@
 makeRsyncRemote name location = makeRemote name location $ const $ void $
 	go =<< Command.InitRemote.findExisting name
   where
-  	go Nothing = setupSpecialRemote name Rsync.remote config Nothing
+	go Nothing = setupSpecialRemote name Rsync.remote config Nothing
 		(Nothing, Command.InitRemote.newConfig name)
 	go (Just (u, c)) = setupSpecialRemote name Rsync.remote config Nothing
 		(Just u, c)
diff --git a/Assistant/NetMessager.hs b/Assistant/NetMessager.hs
--- a/Assistant/NetMessager.hs
+++ b/Assistant/NetMessager.hs
@@ -80,7 +80,7 @@
 queuePushInitiation :: NetMessage -> Assistant ()
 queuePushInitiation msg@(Pushing clientid stage) = do
 	tv <- getPushInitiationQueue side
-  	liftIO $ atomically $ do
+	liftIO $ atomically $ do
 		r <- tryTakeTMVar tv
 		case r of
 			Nothing -> putTMVar tv [msg]
@@ -88,7 +88,7 @@
 				let !l' = msg : filter differentclient l
 				putTMVar tv l'
   where
-  	side = pushDestinationSide stage
+	side = pushDestinationSide stage
 	differentclient (Pushing cid _) = cid /= clientid
 	differentclient _ = True
 queuePushInitiation _ = noop
diff --git a/Assistant/Repair.hs b/Assistant/Repair.hs
--- a/Assistant/Repair.hs
+++ b/Assistant/Repair.hs
@@ -63,7 +63,7 @@
 
 	return ok
   where
-  	localrepair fsckresults = do
+	localrepair fsckresults = do
 		-- Stop the watcher from running while running repairs.
 		changeSyncable Nothing False
 
@@ -140,9 +140,9 @@
 repairStaleLocks :: [FilePath] -> Assistant ()
 repairStaleLocks lockfiles = go =<< getsizes
   where
-  	getsize lf = catchMaybeIO $ 
+	getsize lf = catchMaybeIO $ 
 		(\s -> (lf, fileSize s)) <$> getFileStatus lf
-  	getsizes = liftIO $ catMaybes <$> mapM getsize lockfiles
+	getsizes = liftIO $ catMaybes <$> mapM getsize lockfiles
 	go [] = return ()
 	go l = ifM (liftIO $ null <$> Lsof.query ("--" : map fst l))
 		( do
diff --git a/Assistant/Ssh.hs b/Assistant/Ssh.hs
--- a/Assistant/Ssh.hs
+++ b/Assistant/Ssh.hs
@@ -92,7 +92,7 @@
 		, sshCapabilities = []
 		}
 	  where
-	  	(user, host) = if '@' `elem` userhost
+		(user, host) = if '@' `elem` userhost
 			then separate (== '@') userhost
 			else ("", userhost)
 	fromrsync s
@@ -260,7 +260,7 @@
 fixSshKeyPairIdentitiesOnly :: IO ()
 fixSshKeyPairIdentitiesOnly = changeUserSshConfig $ unlines . go [] . lines
   where
-  	go c [] = reverse c
+	go c [] = reverse c
 	go c (l:[])
 		| all (`isInfixOf` l) indicators = go (fixedline l:l:c) []
 		| otherwise = go (l:c) []
@@ -268,7 +268,7 @@
 		| all (`isInfixOf` l) indicators && not ("IdentitiesOnly" `isInfixOf` next) = 
 			go (fixedline l:l:c) (next:rest)
 		| otherwise = go (l:c) (next:rest)
-  	indicators = ["IdentityFile", "key.git-annex"]
+	indicators = ["IdentityFile", "key.git-annex"]
 	fixedline tmpl = takeWhile isSpace tmpl ++ "IdentitiesOnly yes"
 
 {- Add StrictHostKeyChecking to any ssh config stanzas that were written
diff --git a/Assistant/Threads/Committer.hs b/Assistant/Threads/Committer.hs
--- a/Assistant/Threads/Committer.hs
+++ b/Assistant/Threads/Committer.hs
@@ -164,8 +164,8 @@
 	 -}
 	aftermaxcommit oldchanges = loop (30 :: Int)
 	  where
-	  	loop 0 = continue oldchanges
-	  	loop n = do
+		loop 0 = continue oldchanges
+		loop n = do
 			liftAnnex noop -- ensure Annex state is free
 			liftIO $ threadDelaySeconds (Seconds 1)
 			changes <- getAnyChanges
@@ -301,7 +301,7 @@
 	add change@(InProcessAddChange { keySource = ks }) = 
 		catchDefaultIO Nothing <~> doadd
 	  where
-	  	doadd = sanitycheck ks $ do
+		doadd = sanitycheck ks $ do
 			(mkey, mcache) <- liftAnnex $ do
 				showStart "add" $ keyFilename ks
 				Command.Add.ingest $ Just ks
diff --git a/Assistant/Threads/Cronner.hs b/Assistant/Threads/Cronner.hs
--- a/Assistant/Threads/Cronner.hs
+++ b/Assistant/Threads/Cronner.hs
@@ -87,7 +87,7 @@
 		liftIO $ waitNotification h
 		debug ["reloading changed activities"]
 		go h amap' nmap'
-  	startactivities as lastruntimes = forM as $ \activity ->
+	startactivities as lastruntimes = forM as $ \activity ->
 		case connectActivityUUID activity of
 			Nothing -> do
 				runner <- asIO2 (sleepingActivityThread urlrenderer)
@@ -108,8 +108,8 @@
 sleepingActivityThread :: UrlRenderer -> ScheduledActivity -> Maybe LocalTime -> Assistant ()
 sleepingActivityThread urlrenderer activity lasttime = go lasttime =<< getnexttime lasttime
   where
-  	getnexttime = liftIO . nextTime schedule
-  	go _ Nothing = debug ["no scheduled events left for", desc]
+	getnexttime = liftIO . nextTime schedule
+	go _ Nothing = debug ["no scheduled events left for", desc]
 	go l (Just (NextTimeExactly t)) = waitrun l t Nothing
 	go l (Just (NextTimeWindow windowstart windowend)) =
 		waitrun l windowstart (Just windowend)
@@ -129,7 +129,7 @@
 				go l =<< getnexttime l
 			else run nowt
 	  where
-	  	tolate nowt tz = case mmaxt of
+		tolate nowt tz = case mmaxt of
 			Just maxt -> nowt > maxt
 			-- allow the job to start 10 minutes late
 			Nothing ->diffUTCTime 
diff --git a/Assistant/Threads/SanityChecker.hs b/Assistant/Threads/SanityChecker.hs
--- a/Assistant/Threads/SanityChecker.hs
+++ b/Assistant/Threads/SanityChecker.hs
@@ -258,7 +258,7 @@
 checkOldUnused urlrenderer = go =<< annexExpireUnused <$> liftAnnex Annex.getGitConfig
   where
 	go (Just Nothing) = noop
-  	go (Just (Just expireunused)) = expireUnused (Just expireunused)
+	go (Just (Just expireunused)) = expireUnused (Just expireunused)
 	go Nothing = maybe noop prompt =<< describeUnusedWhenBig
 
 	prompt msg = 
diff --git a/Assistant/Threads/UpgradeWatcher.hs b/Assistant/Threads/UpgradeWatcher.hs
--- a/Assistant/Threads/UpgradeWatcher.hs
+++ b/Assistant/Threads/UpgradeWatcher.hs
@@ -51,9 +51,9 @@
 		let depth = length (splitPath dir) + 1
 		let nosubdirs f = length (splitPath f) == depth
 		void $ liftIO $ watchDir dir nosubdirs False hooks (startup mvar)
-  	-- Ignore bogus events generated during the startup scan.
+	-- Ignore bogus events generated during the startup scan.
 	-- We ask the watcher to not generate them, but just to be safe..
-  	startup mvar scanner = do
+	startup mvar scanner = do
 		r <- scanner
 		void $ swapMVar mvar Started
 		return r
diff --git a/Assistant/Threads/Upgrader.hs b/Assistant/Threads/Upgrader.hs
--- a/Assistant/Threads/Upgrader.hs
+++ b/Assistant/Threads/Upgrader.hs
@@ -39,7 +39,7 @@
 		h <- liftIO . newNotificationHandle False . networkConnectedNotifier =<< getDaemonStatus
 		go h =<< liftIO getCurrentTime
   where
-  	{- Wait for a network connection event. Then see if it's been
+	{- Wait for a network connection event. Then see if it's been
 	 - half a day since the last upgrade check. If so, proceed with
 	 - check. -}
 	go h lastchecked = do
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -72,7 +72,7 @@
 
 {- A special exception that can be thrown to pause or resume the watcher. -}
 data WatcherControl = PauseWatcher | ResumeWatcher
-        deriving (Show, Eq, Typeable)
+	deriving (Show, Eq, Typeable)
 
 instance E.Exception WatcherControl
 
@@ -192,7 +192,7 @@
 			liftAnnex Annex.Queue.flushWhenFull
 			recordChange change
   where
-  	normalize f
+	normalize f
 		| "./" `isPrefixOf` file = drop 2 f
 		| otherwise = f
 
@@ -246,7 +246,7 @@
 				debug ["add direct", file]
 				add matcher file
   where
- 	{- On a filesystem without symlinks, we'll get changes for regular
+	{- On a filesystem without symlinks, we'll get changes for regular
 	 - files that git uses to stand-in for symlinks. Detect when
 	 - this happens, and stage the symlink, rather than annexing the
 	 - file. -}
@@ -276,7 +276,7 @@
 onAddSymlink' :: Maybe String -> Maybe Key -> Bool -> Handler
 onAddSymlink' linktarget mk isdirect file filestatus = go mk
   where
-  	go (Just key) = do
+	go (Just key) = do
 		when isdirect $
 			liftAnnex $ void $ addAssociatedFile key file
 		link <- liftAnnex $ inRepo $ gitAnnexLink file key
diff --git a/Assistant/Threads/WebApp.hs b/Assistant/Threads/WebApp.hs
--- a/Assistant/Threads/WebApp.hs
+++ b/Assistant/Threads/WebApp.hs
@@ -6,6 +6,7 @@
  -}
 
 {-# LANGUAGE TemplateHaskell, MultiParamTypeClasses #-}
+{-# LANGUAGE ViewPatterns, OverloadedStrings #-}
 {-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
@@ -97,7 +98,7 @@
 			urlfile <- getAnnex' $ fromRepo gitAnnexUrlFile
 			go tlssettings addr webapp htmlshim (Just urlfile)
   where
-  	-- The webapp thread does not wait for the startupSanityCheckThread
+	-- The webapp thread does not wait for the startupSanityCheckThread
 	-- to finish, so that the user interface remains responsive while
 	-- that's going on.
 	thread = namedThreadUnchecked "WebApp"
diff --git a/Assistant/Threads/XMPPClient.hs b/Assistant/Threads/XMPPClient.hs
--- a/Assistant/Threads/XMPPClient.hs
+++ b/Assistant/Threads/XMPPClient.hs
@@ -131,7 +131,7 @@
 		{- XEP-0199 says that the server will respond with either
 		 - a ping response or an error message. Either will
 		 - cause traffic, so good enough. -}
-	  	pingstanza = xmppPing selfjid
+		pingstanza = xmppPing selfjid
 
 	handlemsg selfjid (PresenceMessage p) = do
 		void $ inAssistant $ 
diff --git a/Assistant/Threads/XMPPPusher.hs b/Assistant/Threads/XMPPPusher.hs
--- a/Assistant/Threads/XMPPPusher.hs
+++ b/Assistant/Threads/XMPPPusher.hs
@@ -34,7 +34,7 @@
 pusherThread :: String -> PushSide -> UrlRenderer -> NamedThread
 pusherThread threadname side urlrenderer = namedThread threadname $ go Nothing
   where
-  	go lastpushedto = do
+	go lastpushedto = do
 		msg <- waitPushInitiation side $ selectNextPush lastpushedto
 		debug ["started running push", logNetMessage msg]
 
@@ -78,4 +78,4 @@
 		(Pushing clientid _)
 			| Just clientid /= lastpushedto -> (m, rejected ++ ms)
 		_ -> go (m:rejected) ms
-  	go [] [] = undefined
+	go [] [] = undefined
diff --git a/Assistant/TransferQueue.hs b/Assistant/TransferQueue.hs
--- a/Assistant/TransferQueue.hs
+++ b/Assistant/TransferQueue.hs
@@ -92,7 +92,7 @@
 			filterM (wantSend True (Just k) f . Remote.uuid) $
 				filter (\r -> not (inset s r || Remote.readonly r)) rs
 	  where
-	  	locs = S.fromList <$> Remote.keyLocations k
+		locs = S.fromList <$> Remote.keyLocations k
 		inset s r = S.member (Remote.uuid r) s
 	gentransfer r = Transfer
 		{ transferDirection = direction
diff --git a/Assistant/Types/NetMessager.hs b/Assistant/Types/NetMessager.hs
--- a/Assistant/Types/NetMessager.hs
+++ b/Assistant/Types/NetMessager.hs
@@ -85,7 +85,7 @@
 		SendPackOutput n _ -> SendPackOutput n elided
 		s -> s
   where
-  	elided = T.encodeUtf8 $ T.pack "<elided>"
+	elided = T.encodeUtf8 $ T.pack "<elided>"
 logNetMessage (PairingNotification stage c uuid) =
 	show $ PairingNotification stage (logClientID c) uuid
 logNetMessage m = show m
diff --git a/Assistant/Upgrade.hs b/Assistant/Upgrade.hs
--- a/Assistant/Upgrade.hs
+++ b/Assistant/Upgrade.hs
@@ -78,7 +78,7 @@
 startDistributionDownload :: GitAnnexDistribution -> Assistant ()
 startDistributionDownload d = go =<< liftIO . newVersionLocation d =<< liftIO oldVersionLocation
   where
-  	go Nothing = debug ["Skipping redundant upgrade"]
+	go Nothing = debug ["Skipping redundant upgrade"]
 	go (Just dest) = do
 		liftAnnex $ setUrlPresent k u
 		hook <- asIO1 $ distributionDownloadComplete d dest cleanup
diff --git a/Assistant/WebApp/Bootstrap3.hs b/Assistant/WebApp/Bootstrap3.hs
--- a/Assistant/WebApp/Bootstrap3.hs
+++ b/Assistant/WebApp/Bootstrap3.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE CPP #-}
 -- | Helper functions for creating forms when using Bootstrap v3.
 -- This is a copy of the Yesod.Form.Bootstrap3 module that has been slightly
 -- modified to be compatible with Yesod 1.0.1
@@ -149,20 +148,13 @@
 -- >    ^{bootstrapSubmit MsgSubmit}
 --
 -- Since: yesod-form 1.3.8
-#if MIN_VERSION_yesod(1,2,0)
-renderBootstrap3 :: Monad m => BootstrapFormLayout -> FormRender m a
-#else
 renderBootstrap3 :: BootstrapFormLayout -> FormRender sub master a
-#endif
 renderBootstrap3 formLayout aform fragment = do
     (res, views') <- aFormToForm aform
     let views = views' []
         has (Just _) = True
         has Nothing  = False
         widget = [whamlet|
-#if MIN_VERSION_yesod(1,2,0)
-            $newline never
-#endif
             #{fragment}
             $forall view <- views
               <div .form-group :fvRequired view:.required :not $ fvRequired view:.optional :has $ fvErrors view:.has-error>
@@ -193,11 +185,7 @@
     nequals a b = a /= b -- work around older hamlet versions not liking /=
 
 -- | (Internal) Render a help widget for tooltips and errors.
-#if MIN_VERSION_yesod(1,2,0)
-helpWidget :: FieldView site -> WidgetT site IO ()
-#else
 helpWidget :: FieldView sub master -> GWidget sub master ()
-#endif
 helpWidget view = [whamlet|
     $maybe tt <- fvTooltip view
       <span .help-block>#{tt}
@@ -242,13 +230,7 @@
 -- layout.
 --
 -- Since: yesod-form 1.3.8
-#if MIN_VERSION_yesod(1,2,0)
-bootstrapSubmit
-    :: (RenderMessage site msg, HandlerSite m ~ site, MonadHandler m)
-    => BootstrapSubmit msg -> AForm m ()
-#else
 bootstrapSubmit :: (RenderMessage master msg) => BootstrapSubmit msg -> AForm sub master ()
-#endif
 bootstrapSubmit = formToAForm . liftM (second return) . mbootstrapSubmit
 
 
@@ -257,13 +239,7 @@
 -- anyway.
 --
 -- Since: yesod-form 1.3.8
-#if MIN_VERSION_yesod(1,2,0)
-mbootstrapSubmit
-    :: (RenderMessage site msg, HandlerSite m ~ site, MonadHandler m)
-    => BootstrapSubmit msg -> MForm m (FormResult (), FieldView site)
-#else
 mbootstrapSubmit :: (RenderMessage master msg) => BootstrapSubmit msg -> MForm sub master (FormResult (), FieldView sub master)
-#endif
 mbootstrapSubmit (BootstrapSubmit msg classes attrs) =
     let res = FormSuccess ()
         widget = [whamlet|<button class="btn #{classes}" type=submit *{attrs}>_{msg}|]
diff --git a/Assistant/WebApp/Configurators/AWS.hs b/Assistant/WebApp/Configurators/AWS.hs
--- a/Assistant/WebApp/Configurators/AWS.hs
+++ b/Assistant/WebApp/Configurators/AWS.hs
@@ -207,7 +207,7 @@
 	setupCloudRemote defaultgroup Nothing $
 		maker hostname remotetype (Just creds) config
   where
-  	creds = (T.unpack ak, T.unpack sk)
+	creds = (T.unpack ak, T.unpack sk)
 	{- AWS services use the remote name as the basis for a host
 	 - name, so filter it to contain valid characters. -}
 	hostname = case filter isAlphaNum name of
diff --git a/Assistant/WebApp/Configurators/Delete.hs b/Assistant/WebApp/Configurators/Delete.hs
--- a/Assistant/WebApp/Configurators/Delete.hs
+++ b/Assistant/WebApp/Configurators/Delete.hs
@@ -36,7 +36,7 @@
 		then redirect DeleteCurrentRepositoryR
 		else go =<< liftAnnex (Remote.remoteFromUUID uuid)
   where
-  	go Nothing = error "Unknown UUID"
+	go Nothing = error "Unknown UUID"
 	go (Just _) = a
 
 handleXMPPRemoval :: UUID -> Handler Html -> Handler Html
diff --git a/Assistant/WebApp/Configurators/Edit.hs b/Assistant/WebApp/Configurators/Edit.hs
--- a/Assistant/WebApp/Configurators/Edit.hs
+++ b/Assistant/WebApp/Configurators/Edit.hs
@@ -136,7 +136,7 @@
 	when syncableChanged $
 		liftAssistant $ changeSyncable mremote (repoSyncable newc)
   where
-  	syncableChanged = repoSyncable oldc /= repoSyncable newc
+	syncableChanged = repoSyncable oldc /= repoSyncable newc
 	associatedDirectoryChanged = repoAssociatedDirectory oldc /= repoAssociatedDirectory newc
 	groupChanged = repoGroup oldc /= repoGroup newc
 	nameChanged = isJust mremote && legalName oldc /= legalName newc
@@ -255,7 +255,7 @@
 
 getRepoEncryption :: Maybe Remote.Remote -> Maybe Remote.RemoteConfig -> Widget
 getRepoEncryption (Just _) (Just c) = case extractCipher c of
-  	Nothing ->
+	Nothing ->
 		[whamlet|not encrypted|]
 	(Just (SharedCipher _)) ->
 		[whamlet|encrypted: encryption key stored in git repository|]
@@ -274,7 +274,7 @@
 getUpgradeRepositoryR (RepoUUID _) = redirect DashboardR
 getUpgradeRepositoryR r = go =<< liftAnnex (repoIdRemote r)
   where
-  	go Nothing = redirect DashboardR
+	go Nothing = redirect DashboardR
 	go (Just rmt) = do
 		liftIO fixSshKeyPairIdentitiesOnly
 		liftAnnex $ setConfig 
diff --git a/Assistant/WebApp/Configurators/Fsck.hs b/Assistant/WebApp/Configurators/Fsck.hs
--- a/Assistant/WebApp/Configurators/Fsck.hs
+++ b/Assistant/WebApp/Configurators/Fsck.hs
@@ -60,7 +60,7 @@
 	ScheduledSelfFsck s d -> go s d =<< liftAnnex getUUID
 	ScheduledRemoteFsck ru s d -> go s d ru
   where
-  	go (Schedule r t) d ru = do
+	go (Schedule r t) d ru = do
 		u <- liftAnnex getUUID
 		repolist <- liftAssistant (getrepolist ru)
 		runFormPostNoToken $ \msg -> do
diff --git a/Assistant/WebApp/Configurators/IA.hs b/Assistant/WebApp/Configurators/IA.hs
--- a/Assistant/WebApp/Configurators/IA.hs
+++ b/Assistant/WebApp/Configurators/IA.hs
@@ -101,8 +101,8 @@
 
 iaCredsAForm :: Maybe CredPair -> MkAForm AWS.AWSCreds
 iaCredsAForm defcreds = AWS.AWSCreds
-        <$> accessKeyIDFieldWithHelp (T.pack . fst <$> defcreds)
-        <*> AWS.secretAccessKeyField (T.pack . snd <$> defcreds)
+	<$> accessKeyIDFieldWithHelp (T.pack . fst <$> defcreds)
+	<*> AWS.secretAccessKeyField (T.pack . snd <$> defcreds)
 
 #ifdef WITH_S3
 previouslyUsedIACreds :: Annex (Maybe CredPair)
@@ -201,7 +201,7 @@
     have been uploaded, and the Internet Archive has processed them.
 |]
   where
-  	bucket = fromMaybe "" $ M.lookup "bucket" c
+	bucket = fromMaybe "" $ M.lookup "bucket" c
 #ifdef WITH_S3
 	url = S3.iaItemUrl bucket
 #else
diff --git a/Assistant/WebApp/Configurators/Local.hs b/Assistant/WebApp/Configurators/Local.hs
--- a/Assistant/WebApp/Configurators/Local.hs
+++ b/Assistant/WebApp/Configurators/Local.hs
@@ -175,7 +175,7 @@
 getAndroidCameraRepositoryR = 
 	startFullAssistant "/sdcard/DCIM" SourceGroup $ Just addignore	
   where
-  	addignore = do
+	addignore = do
 		liftIO $ unlessM (doesFileExist ".gitignore") $
 			writeFile ".gitignore" ".thumbnails"
 		void $ inRepo $
@@ -274,8 +274,8 @@
 	, newrepo
 	)
   where
-  	dir = removableDriveRepository drive
-  	newrepo = do
+	dir = removableDriveRepository drive
+	newrepo = do
 		secretkeys <- sortBy (comparing snd) . M.toList
 			<$> liftIO secretKeys
 		page "Encrypt repository?" (Just Configuration) $
@@ -338,7 +338,7 @@
 			liftAnnex $ defaultStandardGroup u TransferGroup
 		liftAssistant $ immediateSyncRemote r
 		redirect $ EditNewRepositoryR u
-  	mountpoint = T.unpack (mountPoint drive)
+	mountpoint = T.unpack (mountPoint drive)
 	dir = removableDriveRepository drive
 	remotename = takeFileName mountpoint
 
diff --git a/Assistant/WebApp/Configurators/Pairing.hs b/Assistant/WebApp/Configurators/Pairing.hs
--- a/Assistant/WebApp/Configurators/Pairing.hs
+++ b/Assistant/WebApp/Configurators/Pairing.hs
@@ -72,7 +72,7 @@
 #ifdef WITH_XMPP
 getStartXMPPPairSelfR = go =<< liftAnnex getXMPPCreds
   where
-  	go Nothing = do
+	go Nothing = do
 		-- go get XMPP configured, then come back
 		redirect XMPPConfigForPairSelfR
 	go (Just creds) = do
diff --git a/Assistant/WebApp/Configurators/Ssh.hs b/Assistant/WebApp/Configurators/Ssh.hs
--- a/Assistant/WebApp/Configurators/Ssh.hs
+++ b/Assistant/WebApp/Configurators/Ssh.hs
@@ -193,7 +193,7 @@
 postEnableSshGCryptR u = whenGcryptInstalled $
 	enableSshRemote getsshinput enableRsyncNetGCrypt enablegcrypt u
   where
-  	enablegcrypt sshdata _ = prepSsh False sshdata $ \sshdata' ->
+	enablegcrypt sshdata _ = prepSsh False sshdata $ \sshdata' ->
 		sshConfigurator $
 			checkExistingGCrypt sshdata' $
 				error "Expected to find an encrypted git repository, but did not."
@@ -232,7 +232,7 @@
 				_ -> showform form enctype UntestedServer
 		_ -> redirect AddSshR
   where
-  	unmangle sshdata = sshdata
+	unmangle sshdata = sshdata
 		{ sshHostName = T.pack $ unMangleSshHostName $
 			T.unpack $ sshHostName sshdata
 		}
@@ -423,7 +423,7 @@
 		secretkeys <- sortBy (comparing snd) . M.toList
 			<$> liftIO secretKeys
 		$(widgetFile "configurators/ssh/confirm")
-  	handleexisting Nothing = sshConfigurator $
+	handleexisting Nothing = sshConfigurator $
 		-- Not a UUID we know, so prompt about combining.
 		$(widgetFile "configurators/ssh/combine")
 	handleexisting (Just _) = prepSsh False sshdata $ \sshdata' -> do
@@ -471,7 +471,7 @@
 			combineExistingGCrypt sshdata u
 		Nothing -> error "The location contains a gcrypt repository that is not a git-annex special remote. This is not supported."
   where
-  	repourl = genSshUrl sshdata
+	repourl = genSshUrl sshdata
 
 {- Enables an existing gcrypt special remote. -}
 enableGCrypt :: SshData -> RemoteName -> Handler Html
@@ -488,7 +488,7 @@
 	reponame <- liftAnnex $ getGCryptRemoteName u repourl
 	enableGCrypt sshdata reponame
   where
-  	repourl = genSshUrl sshdata
+	repourl = genSshUrl sshdata
 
 {- Sets up remote repository for ssh, or directory for rsync. -}
 prepSsh :: Bool -> SshData -> (SshData -> Handler Html) -> Handler Html
@@ -579,7 +579,7 @@
 					"That is not a rsync.net host name."
 		_ -> showform UntestedServer
   where
-  	inpage = page "Add a Rsync.net repository" (Just Configuration)
+	inpage = page "Add a Rsync.net repository" (Just Configuration)
 	hostnamefield = textField `withExpandableNote` ("Help", help)
 	help = [whamlet|
 <div>
diff --git a/Assistant/WebApp/Configurators/XMPP.hs b/Assistant/WebApp/Configurators/XMPP.hs
--- a/Assistant/WebApp/Configurators/XMPP.hs
+++ b/Assistant/WebApp/Configurators/XMPP.hs
@@ -150,7 +150,7 @@
 getXMPPRemotes = catMaybes . map pair . filter Remote.isXMPPRemote . syncGitRemotes
 	<$> getDaemonStatus
   where
-  	pair r = maybe Nothing (\jid -> Just (jid, r)) $
+	pair r = maybe Nothing (\jid -> Just (jid, r)) $
 		parseJID $ getXMPPClientID r
 
 data XMPPForm = XMPPForm
@@ -197,8 +197,8 @@
 			}
 		_ -> return $ Left $ intercalate "; " $ map formatlog bad
   where
-  	formatlog ((h, p), Left e) = "host " ++ h ++ ":" ++ showport p ++ " failed: " ++ show e
-  	formatlog _ = ""
+	formatlog ((h, p), Left e) = "host " ++ h ++ ":" ++ showport p ++ " failed: " ++ show e
+	formatlog _ = ""
 
 	showport (PortNumber n) = show n
 	showport (Service s) = s
diff --git a/Assistant/WebApp/Form.hs b/Assistant/WebApp/Form.hs
--- a/Assistant/WebApp/Form.hs
+++ b/Assistant/WebApp/Form.hs
@@ -18,15 +18,16 @@
 #if MIN_VERSION_yesod(1,2,0)
 import Yesod hiding (textField, passwordField)
 import Yesod.Form.Fields as F
+import Yesod.Form.Bootstrap3 hiding (bfs)
 #else
 import Yesod hiding (textField, passwordField, selectField, selectFieldList)
 import Yesod.Form.Fields as F hiding (selectField, selectFieldList)
 import Data.String (IsString (..))
 import Control.Monad (unless)
 import Data.Maybe (listToMaybe)
+import Assistant.WebApp.Bootstrap3 hiding (bfs)
 #endif
 import Data.Text (Text)
-import Assistant.WebApp.Bootstrap3 hiding (bfs)
 
 {- Yesod's textField sets the required attribute for required fields.
  - We don't want this, because many of the forms used in this webapp 
@@ -129,7 +130,7 @@
   ^{note}
 |]
   where
-  	ident = "toggle_" ++ toggle
+	ident = "toggle_" ++ toggle
 
 {- Adds a check box to an AForm to control encryption. -}
 #if MIN_VERSION_yesod(1,2,0)
diff --git a/Assistant/WebApp/RepoId.hs b/Assistant/WebApp/RepoId.hs
--- a/Assistant/WebApp/RepoId.hs
+++ b/Assistant/WebApp/RepoId.hs
@@ -16,7 +16,7 @@
 data RepoId
 	= RepoUUID UUID
 	| RepoName RemoteName
-  deriving (Eq, Ord, Show, Read)
+	deriving (Eq, Ord, Show, Read)
 
 mkRepoId :: Remote -> RepoId
 mkRepoId r = case Remote.uuid r of
diff --git a/Assistant/WebApp/RepoList.hs b/Assistant/WebApp/RepoList.hs
--- a/Assistant/WebApp/RepoList.hs
+++ b/Assistant/WebApp/RepoList.hs
@@ -196,7 +196,7 @@
 				_ -> Nothing
 		_ -> Nothing
 	  where
-	  	getconfig k = M.lookup k =<< M.lookup u m
+		getconfig k = M.lookup k =<< M.lookup u m
 		val iscloud r = Just (iscloud, (RepoUUID u, DisabledRepoActions $ r u))
 	list l = do
 		cc <- currentlyConnectedRemotes <$> liftAssistant getDaemonStatus
@@ -232,13 +232,13 @@
 	liftAssistant updateSyncRemotes
   where
 	go _ Nothing = noop
-  	go list (Just remote) = do
+	go list (Just remote) = do
 		rs <- catMaybes <$> mapM repoIdRemote list
 		forM_ (reorderCosts remote rs) $ \(r, newcost) ->
 			when (Remote.cost r /= newcost) $
 				setRemoteCost (Remote.repo r) newcost
 		void remoteListRefresh
-  	fromjs = fromMaybe (RepoUUID NoUUID) . readish . T.unpack
+	fromjs = fromMaybe (RepoUUID NoUUID) . readish . T.unpack
 
 reorderCosts :: Remote -> [Remote] -> [(Remote, Cost)]
 reorderCosts remote rs = zip rs'' (insertCostAfter costs i)
diff --git a/Assistant/WebApp/Types.hs b/Assistant/WebApp/Types.hs
--- a/Assistant/WebApp/Types.hs
+++ b/Assistant/WebApp/Types.hs
@@ -7,7 +7,7 @@
 
 {-# LANGUAGE TypeFamilies, QuasiQuotes, MultiParamTypeClasses #-}
 {-# LANGUAGE TemplateHaskell, OverloadedStrings, RankNTypes #-}
-{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances, FlexibleContexts, ViewPatterns #-}
 {-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
diff --git a/Assistant/XMPP.hs b/Assistant/XMPP.hs
--- a/Assistant/XMPP.hs
+++ b/Assistant/XMPP.hs
@@ -195,7 +195,7 @@
 		<*> a i
 	gen c i = c . toUUID <$> headMaybe (words (T.unpack (tagValue i)))
 	seqgen c i = do
-	  	packet <- decodeTagContent $ tagElement i
+		packet <- decodeTagContent $ tagElement i
 		let seqnum = fromMaybe 0 $ readish $ T.unpack $ tagValue i
 		return $ c seqnum packet
 	shasgen c i = do
diff --git a/Assistant/XMPP/Git.hs b/Assistant/XMPP/Git.hs
--- a/Assistant/XMPP/Git.hs
+++ b/Assistant/XMPP/Git.hs
@@ -152,7 +152,7 @@
 	
 	fromxmpp outh controlh = withPushMessagesInSequence cid SendPack handlemsg
 	  where
-	  	handlemsg (Just (Pushing _ (ReceivePackOutput _ b))) = 
+		handlemsg (Just (Pushing _ (ReceivePackOutput _ b))) = 
 			liftIO $ writeChunk outh b
 		handlemsg (Just (Pushing _ (ReceivePackDone exitcode))) =
 			liftIO $ do
@@ -266,7 +266,7 @@
 			relaytoxmpp seqnum' outh
 	relayfromxmpp inh = withPushMessagesInSequence cid ReceivePack handlemsg
 	  where
-	  	handlemsg (Just (Pushing _ (SendPackOutput _ b))) =
+		handlemsg (Just (Pushing _ (SendPackOutput _ b))) =
 			liftIO $ writeChunk inh b
 		handlemsg (Just _) = noop
 		handlemsg Nothing = do
@@ -337,7 +337,7 @@
 				, go
 				)
   where
-  	go = do
+	go = do
 		u <- liftAnnex getUUID
 		sendNetMessage $ Pushing cid (PushRequest u)
 	haveall l = liftAnnex $ not <$> anyM donthave l
@@ -359,9 +359,9 @@
 withPushMessagesInSequence :: ClientID -> PushSide -> (Maybe NetMessage -> Assistant ()) -> Assistant ()
 withPushMessagesInSequence cid side a = loop 0
   where
-  	loop seqnum = do
+	loop seqnum = do
 		m <- timeout xmppTimeout <~> waitInbox cid side
-	  	let go s = a m >> loop s
+		let go s = a m >> loop s
 		let next = seqnum + 1
 		case extractSequence =<< m of
 			Just seqnum'
diff --git a/Backend/Hash.hs b/Backend/Hash.hs
--- a/Backend/Hash.hs
+++ b/Backend/Hash.hs
@@ -144,7 +144,7 @@
 hashFile :: Hash -> FilePath -> Integer -> Annex String
 hashFile hash file filesize = liftIO $ go hash
   where
-  	go (SHAHash hashsize) = case shaHasher hashsize filesize of
+	go (SHAHash hashsize) = case shaHasher hashsize filesize of
 		Left sha -> sha <$> L.readFile file
 		Right command ->
 			either error return 
diff --git a/Build/EvilLinker.hs b/Build/EvilLinker.hs
--- a/Build/EvilLinker.hs
+++ b/Build/EvilLinker.hs
@@ -58,13 +58,13 @@
 	collect2params <- restOfLine
 	return $ CmdParams (path ++ collectcmd) (escapeDosPaths collect2params) cenv
   where
-  	collectcmd = "collect2.exe"
-  	collectgccenv = "COLLECT_GCC"
+	collectcmd = "collect2.exe"
+	collectgccenv = "COLLECT_GCC"
 	collectltoenv = "COLLECT_LTO_WRAPPER"
 	pathenv = "COMPILER_PATH"
 	libpathenv = "LIBRARY_PATH"
-  	optenv = "COLLECT_GCC_OPTIONS"
-  	collectenv = do
+	optenv = "COLLECT_GCC_OPTIONS"
+	collectenv = do
 		void $ many1 $ do
 			notFollowedBy $ string collectgccenv
 			restOfLine
@@ -148,7 +148,7 @@
 	removeFile f
 	return out
   where
- 	c = case parse p "" s of
+	c = case parse p "" s of
 		Left e -> error $
 			(show e) ++ 
 			"\n<<<\n" ++ s ++ "\n>>>"
diff --git a/Build/EvilSplicer.hs b/Build/EvilSplicer.hs
--- a/Build/EvilSplicer.hs
+++ b/Build/EvilSplicer.hs
@@ -86,7 +86,7 @@
 coordsParser :: Parser (Coord, Coord)
 coordsParser = (try singleline <|> try weird <|> multiline) <?> "Coords"
   where
-  	singleline = do
+	singleline = do
 		line <- number
 		void $ char ':'
 		startcol <- number
@@ -151,7 +151,7 @@
 				(unlines codelines)
 				splicetype
   where
-  	tosplicetype "declarations" = SpliceDeclaration
+	tosplicetype "declarations" = SpliceDeclaration
 	tosplicetype "expression" = SpliceExpression
 	tosplicetype s = error $ "unknown splice type: " ++ s
 
@@ -177,7 +177,7 @@
 splicesExtractor :: Parser [Splice]
 splicesExtractor = rights <$> many extract
   where
-  	extract = try (Right <$> spliceParser) <|> (Left <$> compilerJunkLine)
+	extract = try (Right <$> spliceParser) <|> (Left <$> compilerJunkLine)
 	compilerJunkLine = restOfLine
 
 {- Modifies the source file, expanding the splices, which all must
@@ -214,8 +214,8 @@
 			hPutStr h newcontent
 		        hClose h
   where
-  	expand lls [] = lls
-  	expand lls (s:rest)
+	expand lls [] = lls
+	expand lls (s:rest)
 		| isExpressionSplice s = expand (expandExpressionSplice s lls) rest
 		| otherwise = expand (expandDeclarationSplice s lls) rest
 
@@ -291,12 +291,12 @@
 		-- ie: bar $(splice)
 		| otherwise = s ++ " $ "
 	  where
-	  	s' = filter (not . isSpace) s
+		s' = filter (not . isSpace) s
 
 	findindent = length . takeWhile isSpace
 	addindent n = unlines . map (i ++) . lines
 	  where
-	  	i = take n $ repeat ' '
+		i = take n $ repeat ' '
 
 {- Tweaks code output by GHC in splices to actually build. Yipes. -}
 mangleCode :: String -> String
@@ -315,7 +315,7 @@
 	. remove_package_version
 	. emptylambda
   where
-  	{- Lambdas are often output without parens around them.
+	{- Lambdas are often output without parens around them.
 	 - This breaks when the lambda is immediately applied to a
 	 - parameter.
 	 - 
@@ -409,7 +409,7 @@
 
 	restofline = manyTill (noneOf "\n") newline
 
-  	{- For some reason, GHC sometimes doesn't like the multiline
+	{- For some reason, GHC sometimes doesn't like the multiline
 	 - strings it creates. It seems to get hung up on \{ at the
 	 - start of a new line sometimes, wanting it to not be escaped.
 	 -
@@ -646,7 +646,7 @@
 	Left _e -> s
 	Right l -> concatMap (either return id) l
   where
-  	find :: Parser [Either Char String]
+	find :: Parser [Either Char String]
 	find = many $ try (Right <$> p) <|> (Left <$> anyChar)
 
 main :: IO ()
@@ -654,7 +654,7 @@
   where
 	go (destdir:log:header:[]) = run destdir log (Just header)
 	go (destdir:log:[]) = run destdir log Nothing
-  	go _ = error "usage: EvilSplicer destdir logfile [headerfile]"
+	go _ = error "usage: EvilSplicer destdir logfile [headerfile]"
 
 	run destdir log mheader = do
 		r <- parseFromFile splicesExtractor log
diff --git a/Build/NullSoftInstaller.hs b/Build/NullSoftInstaller.hs
--- a/Build/NullSoftInstaller.hs
+++ b/Build/NullSoftInstaller.hs
@@ -103,7 +103,7 @@
 	name "git-annex"
 	outFile $ str installer
 	{- Installing into the same directory as git avoids needing to modify
- 	 - path myself, since the git installer already does it. -}
+	 - path myself, since the git installer already does it. -}
 	installDir gitInstallDir
 	requestExecutionLevel Admin
 
diff --git a/Build/OSXMkLibs.hs b/Build/OSXMkLibs.hs
--- a/Build/OSXMkLibs.hs
+++ b/Build/OSXMkLibs.hs
@@ -112,7 +112,7 @@
 		return $ map (replacem m) libs
 	| otherwise = return libs
   where
-  	probe c = "DYLD_PRINT_RPATHS=1 " ++ c ++ " --getting-rpath-dummy-option 2>&1 | grep RPATH"
+	probe c = "DYLD_PRINT_RPATHS=1 " ++ c ++ " --getting-rpath-dummy-option 2>&1 | grep RPATH"
 	parse s = case words s of
 		("RPATH":"successful":"expansion":"of":old:"to:":new:[]) -> 
 			Just (old, new)
diff --git a/Build/Standalone.hs b/Build/Standalone.hs
--- a/Build/Standalone.hs
+++ b/Build/Standalone.hs
@@ -40,7 +40,7 @@
 main = getArgs >>= go
   where
 	go [] = error "specify topdir"
-        go (topdir:_) = do
+	go (topdir:_) = do
 		let dir = progDir topdir
 		createDirectoryIfMissing True dir
 		installed <- forM bundledPrograms $ installProg dir
diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+git-annex (5.20141013) unstable; urgency=medium
+
+  * Adjust cabal file to support building w/o assistant on the hurd.
+  * Support building with yesod 1.4.
+  * S3: Fix embedcreds=yes handling for the Internet Archive.
+  * map: Handle .git prefixed remote repos. Closes: #614759
+  * repair: Prevent auto gc from happening when fetching from a remote.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 13 Oct 2014 10:13:06 -0400
+
 git-annex (5.20140927) unstable; urgency=medium
 
   * Really depend (not just build-depend) on new enough git for --no-gpg-sign
diff --git a/COPYRIGHT b/COPYRIGHT
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -28,6 +28,10 @@
 Copyright: © 2010-2014 Joey Hess <joey@kitenet.net>
 License: GPL-3+
 
+Files: Assistant/WebApp/Bootstrap3.hs
+Copyright: 2010 Michael Snoyman
+License: BSD-2-clause
+
 Files: doc/logo* */favicon.ico standalone/osx/git-annex.app/Contents/Resources/git-annex.icns standalone/android/icons/*
 Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>
            2010 Joey Hess <joey@kitenet.net>
diff --git a/Checks.hs b/Checks.hs
--- a/Checks.hs
+++ b/Checks.hs
@@ -35,7 +35,7 @@
 noDaemonRunning = addCheck $ whenM (isJust <$> daemonpid) $
 	error "You cannot run this command while git-annex watch or git-annex assistant is running."
   where
-  	daemonpid = liftIO . checkDaemon =<< fromRepo gitAnnexPidFile
+	daemonpid = liftIO . checkDaemon =<< fromRepo gitAnnexPidFile
 
 dontCheck :: CommandCheck -> Command -> Command
 dontCheck check cmd = mutateCheck cmd $ \c -> filter (/= check) c
diff --git a/CmdLine.hs b/CmdLine.hs
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -6,7 +6,6 @@
  -}
 
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE BangPatterns #-}
 
 module CmdLine (
 	dispatch,
@@ -58,7 +57,7 @@
 			shutdown $ cmdnocommit cmd
 	go _flags params (Left e) = do
 		when fuzzy $
-	 		autocorrect =<< Git.Config.global
+			autocorrect =<< Git.Config.global
 		maybe (throw e) (\a -> a params) (cmdnorepo cmd)
 	err msg = msg ++ "\n\n" ++ usage header allcmds
 	cmd = Prelude.head cmds
diff --git a/CmdLine/GitAnnexShell.hs b/CmdLine/GitAnnexShell.hs
--- a/CmdLine/GitAnnexShell.hs
+++ b/CmdLine/GitAnnexShell.hs
@@ -66,7 +66,7 @@
 		check u = unexpectedUUID expected u
 	checkGCryptUUID expected = check =<< getGCryptUUID True =<< gitRepo
 	  where
-	  	check (Just u) | u == toUUID expected = noop
+		check (Just u) | u == toUUID expected = noop
 		check Nothing = unexpected expected "uninitialized repository"
 		check (Just u) = unexpectedUUID expected u
 	unexpectedUUID expected u = unexpected expected $ "UUID " ++ fromUUID u
diff --git a/CmdLine/Seek.hs b/CmdLine/Seek.hs
--- a/CmdLine/Seek.hs
+++ b/CmdLine/Seek.hs
@@ -107,7 +107,7 @@
 withFilesUnlocked' typechanged a params = seekActions $
 	prepFiltered a unlockedfiles
   where
-  	check f = liftIO (notSymlink f) <&&> 
+	check f = liftIO (notSymlink f) <&&> 
 		(isJust <$> catKeyFile f <||> isJust <$> catKeyFileHEAD f)
 	unlockedfiles = filterM check =<< seekHelper typechanged params
 
@@ -165,7 +165,7 @@
 			Just k -> go auto $ return [k]
 		_ -> error "Can only specify one of file names, --all, --unused, or --key"
   where
-  	go True _ = error "Cannot use --auto with --all or --unused or --key"
+	go True _ = error "Cannot use --auto with --all or --unused or --key"
 	go False a = do
 		matcher <- Limit.getMatcher
 		seekActions $ map (process matcher) <$> a
diff --git a/Command/Add.hs b/Command/Add.hs
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -125,7 +125,7 @@
 	 - This is not done in direct mode, because files there need to
 	 - remain writable at all times.
 	-}
-  	go tmp = do
+	go tmp = do
 		unlessM isDirect $
 			freezeContent file
 		withTSDelta $ \delta -> liftIO $ do
@@ -134,7 +134,7 @@
 			hClose h
 			nukeFile tmpfile
 			withhardlink delta tmpfile `catchIO` const (nohardlink delta)
-  	nohardlink delta = do
+	nohardlink delta = do
 		cache <- genInodeCache file delta
 		return KeySource
 			{ keyFilename = file
@@ -177,14 +177,14 @@
 			(undo (keyFilename source) key)
 		maybe noop (genMetaData key (keyFilename source)) ms
 		liftIO $ nukeFile $ keyFilename source
-		return $ (Just key, mcache)
+		return (Just key, mcache)
 	goindirect _ _ _ = failure "failed to generate a key"
 
 	godirect (Just (key, _)) (Just cache) ms = do
 		addInodeCache key cache
 		maybe noop (genMetaData key (keyFilename source)) ms
 		finishIngestDirect key source
-		return $ (Just key, Just cache)
+		return (Just key, Just cache)
 	godirect _ _ _ = failure "failed to generate a key"
 
 	failure msg = do
@@ -207,7 +207,7 @@
 perform :: FilePath -> CommandPerform
 perform file = lockDown file >>= ingest >>= go
   where
-  	go (Just key, cache) = next $ cleanup file key cache True
+	go (Just key, cache) = next $ cleanup file key cache True
 	go (Nothing, _) = stop
 
 {- On error, put the file back so it doesn't seem to have vanished.
diff --git a/Command/AddUrl.hs b/Command/AddUrl.hs
--- a/Command/AddUrl.hs
+++ b/Command/AddUrl.hs
@@ -56,7 +56,7 @@
 start :: Bool -> Maybe FilePath -> Maybe Int -> String -> CommandStart
 start relaxed optfile pathdepth s = go $ fromMaybe bad $ parseURI s
   where
-  	(s', downloader) = getDownloader s
+	(s', downloader) = getDownloader s
 	bad = fromMaybe (error $ "bad url " ++ s') $
 		parseURI $ escapeURIString isUnescapedInURI s'
 	choosefile = flip fromMaybe optfile
@@ -95,8 +95,8 @@
 performQuvi :: Bool -> URLString -> URLString -> FilePath -> CommandPerform
 performQuvi relaxed pageurl videourl file = ifAnnexed file addurl geturl
   where
-  	quviurl = setDownloader pageurl QuviDownloader
-  	addurl key = next $ cleanup quviurl file key Nothing
+	quviurl = setDownloader pageurl QuviDownloader
+	addurl key = next $ cleanup quviurl file key Nothing
 	geturl = next $ isJust <$> addUrlFileQuvi relaxed quviurl videourl file
 #endif
 
@@ -189,7 +189,7 @@
 			, return Nothing
 			)
   where
-  	runtransfer dummykey tmp =  Transfer.notifyTransfer Transfer.Download (Just file) $
+	runtransfer dummykey tmp =  Transfer.notifyTransfer Transfer.Download (Just file) $
 		Transfer.download webUUID dummykey (Just file) Transfer.forwardRetry $ const $ do
 			liftIO $ createDirectoryIfMissing True (parentDir tmp)
 			downloadUrl [url] tmp
diff --git a/Command/ConfigList.hs b/Command/ConfigList.hs
--- a/Command/ConfigList.hs
+++ b/Command/ConfigList.hs
@@ -29,7 +29,7 @@
 	showConfig coreGCryptId =<< fromRepo (Git.Config.get coreGCryptId "")
 	stop
   where
-  	showConfig k v = liftIO $ putStrLn $ k ++ "=" ++ v
+	showConfig k v = liftIO $ putStrLn $ k ++ "=" ++ v
 
 {- The repository may not yet have a UUID; automatically initialize it
  - when there's a git-annex branch available. -}
diff --git a/Command/Copy.hs b/Command/Copy.hs
--- a/Command/Copy.hs
+++ b/Command/Copy.hs
@@ -23,7 +23,7 @@
 	to <- getOptionField toOption Remote.byNameWithUUID
 	from <- getOptionField fromOption Remote.byNameWithUUID
 	withKeyOptions
-	 	(Command.Move.startKey to from False)
+		(Command.Move.startKey to from False)
 		(withFilesInGit $ whenAnnexed $ start to from)
 		ps
 
diff --git a/Command/EnableRemote.hs b/Command/EnableRemote.hs
--- a/Command/EnableRemote.hs
+++ b/Command/EnableRemote.hs
@@ -29,7 +29,7 @@
   where
 	config = Logs.Remote.keyValToConfig ws
 	
-  	go Nothing = unknownNameError "Unknown special remote name."
+	go Nothing = unknownNameError "Unknown special remote name."
 	go (Just (u, c)) = do
 		let fullconfig = config `M.union` c	
 		t <- InitRemote.findType fullconfig
diff --git a/Command/Fsck.hs b/Command/Fsck.hs
--- a/Command/Fsck.hs
+++ b/Command/Fsck.hs
@@ -282,7 +282,7 @@
  - the key's metadata, if available.
  -
  - Not checked in direct mode, because files can be changed directly.
-  -}
+ -}
 checkKeySize :: Key -> Annex Bool
 checkKeySize key = ifM isDirect
 	( return True
@@ -329,7 +329,7 @@
 checkBackend :: Backend -> Key -> Maybe FilePath -> Annex Bool
 checkBackend backend key mfile = go =<< isDirect
   where
-  	go False = do
+	go False = do
 		content <- calcRepo $ gitAnnexLocation key
 		checkBackendOr badContent backend key content
 	go True = maybe nocheck checkdirect mfile
diff --git a/Command/FuzzTest.hs b/Command/FuzzTest.hs
--- a/Command/FuzzTest.hs
+++ b/Command/FuzzTest.hs
@@ -47,7 +47,7 @@
 		, "Refusing to run fuzz tests, since " ++ keyname ++ " is not set!"
 		]
   where
-  	key = annexConfig "eat-my-repository"
+	key = annexConfig "eat-my-repository"
 	(ConfigKey keyname) = key
 
 
@@ -257,7 +257,7 @@
 newFile :: IO (Maybe FuzzFile)
 newFile = go (100 :: Int)
   where
-  	go 0 = return Nothing
+	go 0 = return Nothing
 	go n = do
 		f <- genFuzzFile
 		ifM (doesnotexist (toFilePath f))
@@ -268,7 +268,7 @@
 newDir :: FilePath -> IO (Maybe FuzzDir)
 newDir parent = go (100 :: Int)
   where
-  	go 0 = return Nothing
+	go 0 = return Nothing
 	go n = do
 		(FuzzDir d) <- genFuzzDir
 		ifM (doesnotexist (parent </> d))
diff --git a/Command/GCryptSetup.hs b/Command/GCryptSetup.hs
--- a/Command/GCryptSetup.hs
+++ b/Command/GCryptSetup.hs
@@ -30,7 +30,7 @@
 	g <- gitRepo
 	gu <- Remote.GCrypt.getGCryptUUID True g
 	let newgu = genUUIDInNameSpace gCryptNameSpace gcryptid
-	if gu == Nothing || gu == Just newgu
+	if isNothing gu || gu == Just newgu
 		then if Git.repoIsLocalBare g
 			then do
 				void $ Remote.GCrypt.setupRepo gcryptid g
diff --git a/Command/Get.hs b/Command/Get.hs
--- a/Command/Get.hs
+++ b/Command/Get.hs
@@ -48,7 +48,7 @@
 				stopUnless (Command.Move.fromOk src key) $
 					go $ Command.Move.fromPerform src False key afile
   where
-  	go a = do
+	go a = do
 		showStart' "get" key afile
 		next a
 
diff --git a/Command/Import.hs b/Command/Import.hs
--- a/Command/Import.hs
+++ b/Command/Import.hs
@@ -50,8 +50,8 @@
 	<*> getflag cleanDuplicatesOption
 	<*> getflag skipDuplicatesOption
   where
-  	getflag = Annex.getFlag . optionName
-  	gen False False False False = Default
+	getflag = Annex.getFlag . optionName
+	gen False False False False = Default
 	gen True False False False = Duplicate
 	gen False True False False = DeDuplicate
 	gen False False True False = CleanDuplicates
@@ -96,7 +96,7 @@
 	handleexisting Nothing = noop
 	handleexisting (Just s)
 		| isDirectory s = notoverwriting "(is a directory)"
-		| otherwise = ifM (Annex.getState Annex.force) $
+		| otherwise = ifM (Annex.getState Annex.force)
 			( liftIO $ nukeFile destfile
 			, notoverwriting "(use --force to override)"
 			)
diff --git a/Command/ImportFeed.hs b/Command/ImportFeed.hs
--- a/Command/ImportFeed.hs
+++ b/Command/ImportFeed.hs
@@ -153,7 +153,7 @@
 							rundownload videourl ("." ++ Quvi.linkSuffix link) $
 								addUrlFileQuvi relaxed quviurl videourl
   where
-  	forced = Annex.getState Annex.force
+	forced = Annex.getState Annex.force
 
 	{- Avoids downloading any urls that are already known to be
 	 - associated with a file in the annex, unless forced. -}
@@ -192,7 +192,7 @@
 		, return $ Just f
 		)
 	  where
-	  	f = if n < 2
+		f = if n < 2
 			then file
 			else
 				let (d, base) = splitFileName file
diff --git a/Command/Indirect.hs b/Command/Indirect.hs
--- a/Command/Indirect.hs
+++ b/Command/Indirect.hs
@@ -94,7 +94,7 @@
 					warnlocked
 		showEndOk
 
- 	warnlocked :: SomeException -> Annex ()
+	warnlocked :: SomeException -> Annex ()
 	warnlocked e = do
 		warning $ show e
 		warning "leaving this file as-is; correct this problem and run git annex add on it"
diff --git a/Command/Info.hs b/Command/Info.hs
--- a/Command/Info.hs
+++ b/Command/Info.hs
@@ -100,7 +100,7 @@
 	evalStateT (mapM_ showStat stats) =<< getLocalStatInfo dir
 	return True
   where
-  	tostats = map (\s -> s dir)
+	tostats = map (\s -> s dir)
 
 selStats :: [Stat] -> [Stat] -> Annex [Stat]
 selStats fast_stats slow_stats = do
@@ -264,7 +264,7 @@
   where
 	calc x y = multiLine $
 		map (\(n, b) -> b ++ ": " ++ show n) $
-		reverse $ sort $ map swap $ M.toList $
+		sortBy (flip compare) $ map swap $ M.toList $
 		M.unionWith (+) x y
 
 numcopies_stats :: Stat
@@ -273,7 +273,7 @@
   where
 	calc = multiLine
 		. map (\(variance, count) -> show variance ++ ": " ++ show count)
-		. reverse . sortBy (comparing snd) . M.toList
+		. sortBy (flip (comparing snd)) . M.toList
 
 cachedPresentData :: StatState KeyData
 cachedPresentData = do
diff --git a/Command/InitRemote.hs b/Command/InitRemote.hs
--- a/Command/InitRemote.hs
+++ b/Command/InitRemote.hs
@@ -63,7 +63,7 @@
 	return $ headMaybe matches
 
 newConfig :: String -> R.RemoteConfig
-newConfig name = M.singleton nameKey name
+newConfig = M.singleton nameKey
 
 findByName :: String ->  M.Map UUID R.RemoteConfig -> [(UUID, R.RemoteConfig)]
 findByName n = filter (matching . snd) . M.toList
diff --git a/Command/List.hs b/Command/List.hs
--- a/Command/List.hs
+++ b/Command/List.hs
@@ -71,15 +71,15 @@
 header :: [(RemoteName, TrustLevel)] -> String
 header remotes = unlines (zipWith formatheader [0..] remotes) ++ pipes (length remotes)
   where
-    formatheader n (remotename, trustlevel) = pipes n ++ remotename ++ trust trustlevel
-    pipes = flip replicate '|'
-    trust UnTrusted = " (untrusted)"
-    trust _ = ""
+	formatheader n (remotename, trustlevel) = pipes n ++ remotename ++ trust trustlevel
+	pipes = flip replicate '|'
+	trust UnTrusted = " (untrusted)"
+	trust _ = ""
 
 format :: [(TrustLevel, Present)] -> FilePath -> String
 format remotes file = thereMap ++ " " ++ file
   where 
-    thereMap = concatMap there remotes
-    there (UnTrusted, True) = "x"
-    there (_, True) = "X"
-    there (_, False) = "_"
+	thereMap = concatMap there remotes
+	there (UnTrusted, True) = "x"
+	there (_, True) = "X"
+	there (_, False) = "_"
diff --git a/Command/Map.hs b/Command/Map.hs
--- a/Command/Map.hs
+++ b/Command/Map.hs
@@ -206,14 +206,15 @@
 		sshparams <- Ssh.toRepo r gc [Param sshcmd]
 		liftIO $ pipedconfig "ssh" sshparams
 	  where
-		sshcmd = cddir ++ " && " ++
-			"git config --null --list"
+		sshcmd = "sh -c " ++ shellEscape
+			(cddir ++ " && " ++ "git config --null --list")
 		dir = Git.repoPath r
 		cddir
 			| "/~" `isPrefixOf` dir =
 				let (userhome, reldir) = span (/= '/') (drop 1 dir)
-				in "cd " ++ userhome ++ " && cd " ++ shellEscape (drop 1 reldir)
-			| otherwise = "cd " ++ shellEscape dir
+				in "cd " ++ userhome ++ " && " ++ cdto (drop 1 reldir)
+			| otherwise = cdto dir
+		cdto dir = "if ! cd " ++ shellEscape dir ++ " 2>/dev/null; then cd " ++ shellEscape dir ++ ".git; fi"
 
 	-- First, try sshing and running git config manually,
 	-- only fall back to git-annex-shell configlist if that
diff --git a/Command/Migrate.hs b/Command/Migrate.hs
--- a/Command/Migrate.hs
+++ b/Command/Migrate.hs
@@ -65,7 +65,7 @@
 perform :: FilePath -> Key -> Backend -> Backend -> CommandPerform
 perform file oldkey oldbackend newbackend = go =<< genkey
   where
-  	go Nothing = stop
+	go Nothing = stop
 	go (Just (newkey, knowngoodcontent))
 		| knowngoodcontent = finish newkey
 		| otherwise = stopUnless checkcontent $ finish newkey
diff --git a/Command/Mirror.hs b/Command/Mirror.hs
--- a/Command/Mirror.hs
+++ b/Command/Mirror.hs
@@ -32,7 +32,7 @@
 		ps
 
 start :: Maybe Remote -> Maybe Remote -> FilePath -> Key -> CommandStart
-start to from file key = startKey to from (Just file) key
+start to from file = startKey to from (Just file)
 
 startKey :: Maybe Remote -> Maybe Remote -> Maybe FilePath -> Key -> CommandStart
 startKey to from afile key = do
diff --git a/Command/Move.hs b/Command/Move.hs
--- a/Command/Move.hs
+++ b/Command/Move.hs
@@ -34,7 +34,7 @@
 		ps
 
 start :: Maybe Remote -> Maybe Remote -> Bool -> FilePath -> Key -> CommandStart
-start to from move file key = start' to from move (Just file) key
+start to from move = start' to from move . Just
 
 startKey :: Maybe Remote -> Maybe Remote -> Bool -> Key -> CommandStart
 startKey to from move = start' to from move Nothing
@@ -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 = do
+toPerform dest move key afile fastcheck isthere =
 	case isthere of
 		Left err -> do
 			showNote err
diff --git a/Command/NotifyChanges.hs b/Command/NotifyChanges.hs
--- a/Command/NotifyChanges.hs
+++ b/Command/NotifyChanges.hs
@@ -51,7 +51,7 @@
 	
 	-- No messages need to be received from the caller,
 	-- but when it closes the connection, notice and terminate.
-	let receiver = forever $ void $ getLine
+	let receiver = forever $ void getLine
 	void $ liftIO $ concurrently sender receiver
 	stop
 
diff --git a/Command/NumCopies.hs b/Command/NumCopies.hs
--- a/Command/NumCopies.hs
+++ b/Command/NumCopies.hs
@@ -22,16 +22,15 @@
 
 start :: [String] -> CommandStart
 start [] = startGet
-start [s] = do
-	case readish s of
-		Nothing -> error $ "Bad number: " ++ s
-		Just n
-			| n > 0 -> startSet n
-			| n == 0 -> ifM (Annex.getState Annex.force)
-				( startSet n
-				, error "Setting numcopies to 0 is very unsafe. You will lose data! If you really want to do that, specify --force."
-				)
-			| otherwise -> error "Number cannot be negative!"
+start [s] = case readish s of
+	Nothing -> error $ "Bad number: " ++ s
+	Just n
+		| n > 0 -> startSet n
+		| n == 0 -> ifM (Annex.getState Annex.force)
+			( startSet n
+			, error "Setting numcopies to 0 is very unsafe. You will lose data! If you really want to do that, specify --force."
+			)
+		| otherwise -> error "Number cannot be negative!"
 start _ = error "Specify a single number."
 
 startGet :: CommandStart
@@ -39,9 +38,9 @@
 	Annex.setOutput QuietOutput
 	v <- getGlobalNumCopies
 	case v of
-		Just n -> liftIO $ putStrLn $ show $ fromNumCopies n
+		Just n -> liftIO $ print $ fromNumCopies n
 		Nothing -> do
-			liftIO $ putStrLn $ "global numcopies is not set"
+			liftIO $ putStrLn "global numcopies is not set"
 			old <- deprecatedNumCopies
 			case old of
 				Nothing -> liftIO $ putStrLn "(default is 1)"
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -59,7 +59,7 @@
 	next $ return True
 
 startDirect :: [String] -> CommandStart
-startDirect _ = next $ next $ preCommitDirect
+startDirect _ = next $ next preCommitDirect
 
 addViewMetaData :: View -> ViewedFile -> Key -> CommandStart
 addViewMetaData v f k = do
diff --git a/Command/RecvKey.hs b/Command/RecvKey.hs
--- a/Command/RecvKey.hs
+++ b/Command/RecvKey.hs
@@ -63,7 +63,7 @@
 		        Nothing -> return True
 		        Just size -> do
 				size' <- fromIntegral . fileSize
-       	        	        	<$> liftIO (getFileStatus tmp)
+					<$> liftIO (getFileStatus tmp)
 				return $ size == size'
 		if oksize
 			then case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of
@@ -76,7 +76,7 @@
 				warning "recvkey: received key with wrong size; discarding"
 				return False
 	  where
-	  	runfsck check = ifM (check key tmp)
+		runfsck check = ifM (check key tmp)
 			( return True
 			, do
 				warning "recvkey: received key from direct mode repository seems to have changed as it was transferred; discarding"
diff --git a/Command/Repair.hs b/Command/Repair.hs
--- a/Command/Repair.hs
+++ b/Command/Repair.hs
@@ -68,7 +68,7 @@
 				)
 		)
   where
-	okindex = Annex.Branch.withIndex $ inRepo $ Git.Repair.checkIndex
+	okindex = Annex.Branch.withIndex $ inRepo Git.Repair.checkIndex
 	commitindex = do
 		Annex.Branch.forceCommit "committing index after git repository repair"
 		liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index"
diff --git a/Command/ResolveMerge.hs b/Command/ResolveMerge.hs
--- a/Command/ResolveMerge.hs
+++ b/Command/ResolveMerge.hs
@@ -19,7 +19,7 @@
 	"resolve merge conflicts"]
 
 seek :: CommandSeek
-seek ps = withNothing start ps
+seek = withNothing start
 
 start :: CommandStart
 start = do
diff --git a/Command/Schedule.hs b/Command/Schedule.hs
--- a/Command/Schedule.hs
+++ b/Command/Schedule.hs
@@ -27,7 +27,7 @@
 start :: [String] -> CommandStart
 start = parse
   where
-  	parse (name:[]) = go name performGet
+	parse (name:[]) = go name performGet
 	parse (name:expr:[]) = go name $ \uuid -> do
 		showStart "schedile" name
 		performSet expr uuid
diff --git a/Command/Sync.hs b/Command/Sync.hs
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -356,7 +356,7 @@
 	handleDropsFrom locs' rs "unwanted" True k (Just f)
 		Nothing callCommandAction
   where
-  	wantget have = allM id 
+	wantget have = allM id 
 		[ pure (not $ null have)
 		, not <$> inAnnex k
 		, wantGet True (Just k) (Just f)
diff --git a/Command/TransferKeys.hs b/Command/TransferKeys.hs
--- a/Command/TransferKeys.hs
+++ b/Command/TransferKeys.hs
@@ -57,7 +57,7 @@
 		fileEncoding writeh
 	go =<< readrequests
   where
-  	go (d:rn:k:f:rest) = do
+	go (d:rn:k:f:rest) = do
 		case (deserialize d, deserialize rn, deserialize k, deserialize f) of
 			(Just direction, Just remotename, Just key, Just file) -> do
 				mremote <- Remote.byName' remotename
diff --git a/Command/Uninit.hs b/Command/Uninit.hs
--- a/Command/Uninit.hs
+++ b/Command/Uninit.hs
@@ -100,7 +100,7 @@
 removeUnannexed :: [Key] -> Annex [Key]
 removeUnannexed = go []
   where
-  	go c [] = return c
+	go c [] = return c
 	go c (k:ks) = ifM (inAnnexCheck k $ liftIO . enoughlinks)
 		( do
 			lockContent k removeAnnex
diff --git a/Command/Vicfg.hs b/Command/Vicfg.hs
--- a/Command/Vicfg.hs
+++ b/Command/Vicfg.hs
@@ -136,7 +136,7 @@
 		(\(s, u) -> line "group" u $ unwords $ S.toList s)
 		(\u -> lcom $ line "group" u "")
 	  where
-	  	grouplist = unwords $ map fromStandardGroup [minBound..]
+		grouplist = unwords $ map fromStandardGroup [minBound..]
 
 	preferredcontent = settings cfg descs cfgPreferredContentMap
 		[ com "Repository preferred contents"
@@ -157,7 +157,7 @@
 		(\(s, g) -> gline g s)
 		(\g -> gline g "")
 	  where
-	  	gline g value = [ unwords ["groupwanted", g, "=", value] ]
+		gline g value = [ unwords ["groupwanted", g, "=", value] ]
 		allgroups = S.unions $ stdgroups : M.elems (cfgGroupMap cfg)
 		stdgroups = S.fromList $ map fromStandardGroup [minBound..maxBound]
 
diff --git a/Command/Wanted.hs b/Command/Wanted.hs
--- a/Command/Wanted.hs
+++ b/Command/Wanted.hs
@@ -26,7 +26,7 @@
 start :: [String] -> CommandStart
 start = parse
   where
-  	parse (name:[]) = go name performGet
+	parse (name:[]) = go name performGet
 	parse (name:expr:[]) = go name $ \uuid -> do
 		showStart "wanted" name
 		performSet expr uuid
diff --git a/Config/Cost.hs b/Config/Cost.hs
--- a/Config/Cost.hs
+++ b/Config/Cost.hs
@@ -52,7 +52,7 @@
 	| otherwise =
 		firstsegment ++ [costBetween item nextitem ] ++ lastsegment
   where
-  	nextpos = pos + 1
+	nextpos = pos + 1
 	maxpos = length l - 1
 	
 	item = l !! pos
diff --git a/Config/Files.hs b/Config/Files.hs
--- a/Config/Files.hs
+++ b/Config/Files.hs
@@ -66,4 +66,4 @@
 			)
 		)
   where
-  	cmd = "git-annex"
+	cmd = "git-annex"
diff --git a/Git/CatFile.hs b/Git/CatFile.hs
--- a/Git/CatFile.hs
+++ b/Git/CatFile.hs
@@ -94,7 +94,7 @@
 catTree h treeref = go <$> catObjectDetails h treeref
   where
 	go (Just (b, _, TreeObject)) = parsetree [] b
-  	go _ = []
+	go _ = []
 
 	parsetree c b = case L.break (== 0) b of
 		(modefile, rest)
diff --git a/Git/Command.hs b/Git/Command.hs
--- a/Git/Command.hs
+++ b/Git/Command.hs
@@ -79,7 +79,7 @@
 	writeReadProcessEnv "git" (toCommand $ gitCommandLine params repo) 
 		(gitEnv repo) writer (Just adjusthandle)
   where
-  	adjusthandle h = do
+	adjusthandle h = do
 		fileEncoding h
 		hSetNewlineMode h noNewlineTranslation
 
@@ -117,7 +117,7 @@
 	(toCommand $ gitCommandLine params repo)
 	(gitEnv repo)
   where
-  	{- If a long-running git command like cat-file --batch
+	{- If a long-running git command like cat-file --batch
 	 - crashes, it will likely start up again ok. If it keeps crashing
 	 - 10 times, something is badly wrong. -}
 	numrestarts = if restartable then 10 else 0
diff --git a/Git/Config.hs b/Git/Config.hs
--- a/Git/Config.hs
+++ b/Git/Config.hs
@@ -167,7 +167,7 @@
 fromPipe :: Repo -> String -> [CommandParam] -> IO (Either SomeException (Repo, String))
 fromPipe r cmd params = try $
 	withHandle StdoutHandle createProcessSuccess p $ \h -> do
- 		fileEncoding h
+		fileEncoding h
 		val <- hGetContentsStrict h
 		r' <- store val r
 		return (r', val)
diff --git a/Git/DiffTree.hs b/Git/DiffTree.hs
--- a/Git/DiffTree.hs
+++ b/Git/DiffTree.hs
@@ -53,7 +53,7 @@
 diffWorkTree :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
 diffWorkTree ref repo =
 	ifM (Git.Ref.headExists repo)
-                ( diffIndex' ref [] repo
+		( diffIndex' ref [] repo
 		, return ([], return True)
 		)
 
diff --git a/Git/GCrypt.hs b/Git/GCrypt.hs
--- a/Git/GCrypt.hs
+++ b/Git/GCrypt.hs
@@ -38,12 +38,12 @@
 encryptedRemote :: Repo -> Repo -> IO Repo
 encryptedRemote baserepo = go
   where
-  	go Repo { location = Url url }
+	go Repo { location = Url url }
 		| urlPrefix `isPrefixOf` u =
 			fromRemoteLocation (drop plen u) baserepo
 		| otherwise = notencrypted
 	  where
-  		u = show url
+		u = show url
 		plen = length urlPrefix
 	go _ = notencrypted
 	notencrypted = error "not a gcrypt encrypted repository"
@@ -92,7 +92,7 @@
 	]
   where
 	defaultkey = "gcrypt.participants"
-  	parse (Just "simple") = []
+	parse (Just "simple") = []
 	parse (Just l) = words l
 	parse Nothing = []
 
diff --git a/Git/LsTree.hs b/Git/LsTree.hs
--- a/Git/LsTree.hs
+++ b/Git/LsTree.hs
@@ -44,7 +44,7 @@
 lsTreeFiles :: Ref -> [FilePath] -> Repo -> IO [TreeItem]
 lsTreeFiles t fs repo = map parseLsTree <$> pipeNullSplitStrict ps repo
   where
-  	ps = [Params "ls-tree --full-tree -z --", File $ fromRef t] ++ map File fs
+	ps = [Params "ls-tree --full-tree -z --", File $ fromRef t] ++ map File fs
 
 {- Parses a line of ls-tree output.
  - (The --long format is not currently supported.) -}
diff --git a/Git/Remote.hs b/Git/Remote.hs
--- a/Git/Remote.hs
+++ b/Git/Remote.hs
@@ -70,7 +70,7 @@
 parseRemoteLocation :: String -> Repo -> RemoteLocation
 parseRemoteLocation s repo = ret $ calcloc s
   where
-  	ret v
+	ret v
 #ifdef mingw32_HOST_OS
 		| dosstyle v = RemotePath (dospath v)
 #endif
diff --git a/Git/Repair.hs b/Git/Repair.hs
--- a/Git/Repair.hs
+++ b/Git/Repair.hs
@@ -135,11 +135,16 @@
 							pullremotes tmpr rmts fetchrefs (FsckFoundMissing stillmissing t)
 				, pullremotes tmpr rmts fetchrefs ms
 				)
-	fetchfrom fetchurl ps = runBool $
-		[ Param "fetch"
-		, Param fetchurl
-		, Params "--force --update-head-ok --quiet"
-		] ++ ps
+	fetchfrom fetchurl ps fetchr = runBool ps' fetchr'
+	  where
+		ps' = 
+			[ Param "fetch"
+			, Param fetchurl
+			, Params "--force --update-head-ok --quiet"
+			] ++ ps
+		fetchr' = fetchr { gitGlobalOpts = gitGlobalOpts fetchr ++ nogc }
+		nogc = [ Param "-c", Param "gc.auto=0" ]
+
 	-- fetch refs and tags
 	fetchrefstags = [ Param "+refs/heads/*:refs/heads/*", Param "--tags"]
 	-- Fetch all available refs (more likely to fail,
@@ -222,7 +227,7 @@
 getAllRefs :: Repo -> IO [Ref]
 getAllRefs r = map toref <$> dirContentsRecursive refdir
   where
-  	refdir = localGitDir r </> "refs"
+	refdir = localGitDir r </> "refs"
 	toref = Ref . relPathDirToFile (localGitDir r)
 
 explodePackedRefsFile :: Repo -> IO ()
@@ -411,7 +416,7 @@
 		putStrLn header
 		putStr $ unlines $ map (\i -> "\t" ++ i) truncateditems
   where
-  	numitems = length items
+	numitems = length items
 	truncateditems
 		| numitems > 10 = take 10 items ++ ["(and " ++ show (numitems - 10) ++ " more)"]
 		| otherwise = items
diff --git a/Git/Version.hs b/Git/Version.hs
--- a/Git/Version.hs
+++ b/Git/Version.hs
@@ -21,7 +21,7 @@
 installed :: IO GitVersion
 installed = normalize . extract <$> readProcess "git" ["--version"]
   where
-  	extract s = case lines s of
+	extract s = case lines s of
 		[] -> ""
 		(l:_) -> unwords $ drop 2 $ words l
 
diff --git a/Limit.hs b/Limit.hs
--- a/Limit.hs
+++ b/Limit.hs
@@ -82,7 +82,7 @@
 limitExclude :: MkLimit Annex
 limitExclude glob = Right $ const $ return . not . matchGlobFile glob
 
-matchGlobFile :: String -> (MatchInfo -> Bool)
+matchGlobFile :: String -> MatchInfo -> Bool
 matchGlobFile glob = go
 	where
 		cglob = compileGlob glob CaseSensative -- memoized
@@ -234,7 +234,7 @@
 	Nothing -> Left "bad size"
 	Just sz -> Right $ go sz
   where
-  	go sz _ (MatchingFile fi) = lookupFileKey fi >>= check fi sz
+	go sz _ (MatchingFile fi) = lookupFileKey fi >>= check fi sz
 	go sz _ (MatchingKey key) = checkkey sz key
 	checkkey sz key = return $ keySize key `vs` Just sz
 	check _ sz (Just key) = checkkey sz key
@@ -254,7 +254,7 @@
 		let cglob = compileGlob (fromMetaValue v) CaseInsensative
 		in Right $ const $ checkKey (check f cglob)
   where
-  	check f cglob k = not . S.null 
+	check f cglob k = not . S.null 
 		. S.filter (matchGlob cglob . fromMetaValue) 
 		. metaDataValues f <$> getCurrentMetaData k
 
diff --git a/Locations.hs b/Locations.hs
--- a/Locations.hs
+++ b/Locations.hs
@@ -148,7 +148,7 @@
 	loc <- gitAnnexLocation' key r False
 	return $ relPathDirToFile (parentDir absfile) loc
   where
-  	whoops = error $ "unable to normalize " ++ file
+	whoops = error $ "unable to normalize " ++ file
 
 {- File used to lock a key's content. -}
 gitAnnexContentLock :: Key -> Git.Repo -> GitConfig -> IO FilePath
@@ -356,7 +356,7 @@
 preSanitizeKeyName :: String -> String
 preSanitizeKeyName = concatMap escape
   where
-  	escape c
+	escape c
 		| isAsciiUpper c || isAsciiLower c || isDigit c = [c]
 		| c `elem` ".-_ " = [c] -- common, assumed safe
 		| c `elem` "/%:" = [c] -- handled by keyFile
diff --git a/Logs.hs b/Logs.hs
--- a/Logs.hs
+++ b/Logs.hs
@@ -90,11 +90,11 @@
 locationLogFileKey :: FilePath -> Maybe Key
 locationLogFileKey path
 	| ["remote", "web"] `isPrefixOf` splitDirectories dir = Nothing
-        | ext == ".log" = fileKey base
-        | otherwise = Nothing
+	| ext == ".log" = fileKey base
+	| otherwise = Nothing
   where
 	(dir, file) = splitFileName path
-        (base, ext) = splitAt (length file - 4) file
+	(base, ext) = splitAt (length file - 4) file
 
 {- The filename of the url log for a given key. -}
 urlLogFile :: Key -> FilePath
@@ -117,7 +117,7 @@
 	| ext == urlLogExt = fileKey base
 	| otherwise = Nothing
   where
-  	file = takeFileName path
+	file = takeFileName path
 	(base, ext) = splitAt (length file - extlen) file
 	extlen = length urlLogExt
 
@@ -144,7 +144,7 @@
 	| ext == chunkLogExt = fileKey base
 	| otherwise = Nothing
   where
-  	file = takeFileName path
+	file = takeFileName path
 	(base, ext) = splitAt (length file - extlen) file
 	extlen = length chunkLogExt
 
@@ -173,13 +173,13 @@
 	, expect gotNewUUIDBasedLog (getLogVariety $ remoteStateLogFile dummykey)
 	, expect gotChunkLog (getLogVariety $ chunkLogFile dummykey)
 	, expect gotOtherLog (getLogVariety $ metaDataLogFile dummykey)
-	, expect gotOtherLog (getLogVariety $ numcopiesLog)
+	, expect gotOtherLog (getLogVariety numcopiesLog)
 	]
   where
-  	expect = maybe False
+	expect = maybe False
 	gotUUIDBasedLog UUIDBasedLog = True
 	gotUUIDBasedLog _ = False
-  	gotNewUUIDBasedLog NewUUIDBasedLog = True
+	gotNewUUIDBasedLog NewUUIDBasedLog = True
 	gotNewUUIDBasedLog _ = False
 	gotChunkLog (ChunkLog k) = k == dummykey
 	gotChunkLog _ = False
diff --git a/Logs/FsckResults.hs b/Logs/FsckResults.hs
--- a/Logs/FsckResults.hs
+++ b/Logs/FsckResults.hs
@@ -28,7 +28,7 @@
 				| S.null s -> nukeFile logfile
 				| otherwise -> store s t logfile
   where
-  	store s t logfile = do 
+	store s t logfile = do 
 		createDirectoryIfMissing True (parentDir logfile)
 		liftIO $ viaTmp writeFile logfile $ serialize s t
 	serialize s t =
diff --git a/Logs/MapLog.hs b/Logs/MapLog.hs
--- a/Logs/MapLog.hs
+++ b/Logs/MapLog.hs
@@ -15,7 +15,7 @@
 import Data.Time.Clock.POSIX
 import Data.Time
 import System.Locale
-  
+
 import Common
 
 data TimeStamp = Unknown | Date POSIXTime
diff --git a/Logs/MetaData.hs b/Logs/MetaData.hs
--- a/Logs/MetaData.hs
+++ b/Logs/MetaData.hs
@@ -67,7 +67,7 @@
 	return $ currentMetaData $ unionMetaData loggedmeta
 		(lastchanged ls loggedmeta)
   where
-  	lastchanged [] _ = emptyMetaData
+	lastchanged [] _ = emptyMetaData
 	lastchanged ls (MetaData currentlyset) =
 		let m = foldl' (flip M.union) M.empty (map genlastchanged ls)
 		in MetaData $
diff --git a/Logs/Schedule.hs b/Logs/Schedule.hs
--- a/Logs/Schedule.hs
+++ b/Logs/Schedule.hs
@@ -35,7 +35,7 @@
 	Annex.Branch.change scheduleLog $
 		showLog id . changeLog ts uuid val . parseLog Just
   where
-  	val = fromScheduledActivities activities
+	val = fromScheduledActivities activities
 scheduleSet NoUUID _ = error "unknown UUID; cannot modify"
 
 scheduleMap :: Annex (M.Map UUID [ScheduledActivity])
diff --git a/Logs/SingleValue.hs b/Logs/SingleValue.hs
--- a/Logs/SingleValue.hs
+++ b/Logs/SingleValue.hs
@@ -60,6 +60,6 @@
 
 setLog :: (SingleValueSerializable v) => FilePath -> v -> Annex ()
 setLog f v = do
-        now <- liftIO getPOSIXTime
-        let ent = LogEntry now v
+	now <- liftIO getPOSIXTime
+	let ent = LogEntry now v
 	Annex.Branch.change f $ \_old -> showLog (S.singleton ent)
diff --git a/Logs/Transitions.hs b/Logs/Transitions.hs
--- a/Logs/Transitions.hs
+++ b/Logs/Transitions.hs
@@ -53,7 +53,7 @@
 parseTransitions :: String -> Maybe Transitions
 parseTransitions = check . map parseTransitionLine . lines
   where
-  	check l
+	check l
 		| all isJust l = Just $ S.fromList $ catMaybes l
 		| otherwise = Nothing
 
@@ -68,8 +68,8 @@
 parseTransitionLine :: String -> Maybe TransitionLine
 parseTransitionLine s = TransitionLine <$> pdate ds <*> readish ts
   where
-  	ws = words s
-  	ts = Prelude.head ws
+	ws = words s
+	ts = Prelude.head ws
 	ds = unwords $ Prelude.tail ws
 	pdate = utcTimeToPOSIXSeconds <$$> parseTime defaultTimeLocale "%s%Qs"
 
diff --git a/Logs/Web.hs b/Logs/Web.hs
--- a/Logs/Web.hs
+++ b/Logs/Web.hs
@@ -76,7 +76,7 @@
 		return $ concat r
   where
 	geturls Nothing = return []
-  	geturls (Just logsha) = getLog . L.unpack <$> catObject logsha
+	geturls (Just logsha) = getLog . L.unpack <$> catObject logsha
 
 data Downloader = DefaultDownloader | QuviDownloader
 
diff --git a/Remote.hs b/Remote.hs
--- a/Remote.hs
+++ b/Remote.hs
@@ -101,14 +101,14 @@
 byNameWithUUID :: Maybe RemoteName -> Annex (Maybe Remote)
 byNameWithUUID = checkuuid <=< byName
   where
-  	checkuuid Nothing = return Nothing
+	checkuuid Nothing = return Nothing
 	checkuuid (Just r)
-		| uuid r == NoUUID =
+		| uuid r == NoUUID = error $
 			if remoteAnnexIgnore (gitconfig r)
-				then error $ noRemoteUUIDMsg r ++
+				then noRemoteUUIDMsg r ++
 					" (" ++ show (remoteConfig (repo r) "ignore") ++
 					" is set)"
-				else error $ noRemoteUUIDMsg r
+				else noRemoteUUIDMsg r
 		| otherwise = return $ Just r
 
 byName' :: RemoteName -> Annex (Either String Remote)
diff --git a/Remote/External.hs b/Remote/External.hs
--- a/Remote/External.hs
+++ b/Remote/External.hs
@@ -169,7 +169,7 @@
 		go
 	| otherwise = go
   where
-  	go = do
+	go = do
 		sendMessage lck external req
 		loop
 	loop = receiveMessage lck external responsehandler
diff --git a/Remote/GCrypt.hs b/Remote/GCrypt.hs
--- a/Remote/GCrypt.hs
+++ b/Remote/GCrypt.hs
@@ -147,7 +147,7 @@
 	| ":" `isInfixOf` loc = sshtransport $ separate (== ':') loc
 	| otherwise = othertransport
   where
-  	loc = Git.repoLocation r
+	loc = Git.repoLocation r
 	sshtransport (host, path) = do
 		let rsyncpath = if "/~/" `isPrefixOf` path
 			then drop 3 path
@@ -166,7 +166,7 @@
 gCryptSetup mu _ c = go $ M.lookup "gitrepo" c
   where
 	remotename = fromJust (M.lookup "name" c)
-  	go Nothing = error "Specify gitrepo="
+	go Nothing = error "Specify gitrepo="
 	go (Just gitrepo) = do
 		(c', _encsetup) <- encryptionSetup c
 		inRepo $ Git.Command.run 
@@ -234,7 +234,7 @@
 	 - create the objectDir on the remote,
 	 - which is needed for direct rsync of objects to work.
 	 -}
-  	rsyncsetup = Remote.Rsync.withRsyncScratchDir $ \tmp -> do
+	rsyncsetup = Remote.Rsync.withRsyncScratchDir $ \tmp -> do
 		liftIO $ createDirectoryIfMissing True $ tmp </> objectDir
 		(rsynctransport, rsyncurl, _) <- rsyncTransport r
 		let tmpconfig = tmp </> "config"
@@ -266,7 +266,7 @@
 	AccessShell -> True
 	_ -> False
   where
-  	method = toAccessMethod $ fromMaybe "" $
+	method = toAccessMethod $ fromMaybe "" $
 		remoteAnnexGCrypt $ gitconfig r
 
 shellOrRsync :: Remote -> Annex a -> Annex a -> Annex a
@@ -352,7 +352,7 @@
 	| Git.repoIsSsh (repo r) = shellOrRsync r checkshell checkrsync
 	| otherwise = unsupportedUrl
   where
-  	checkrsync = Remote.Rsync.checkKey (repo r) rsyncopts k
+	checkrsync = Remote.Rsync.checkKey (repo r) rsyncopts k
 	checkshell = Ssh.inAnnex (repo r) k
 
 {- Annexed objects are hashed using lower-case directories for max
diff --git a/Remote/Git.hs b/Remote/Git.hs
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -305,7 +305,7 @@
 	| Git.repoIsUrl r = checkremote
 	| otherwise = checklocal
   where
-  	r = repo rmt
+	r = repo rmt
 	checkhttp = do
 		showChecking r
 		ifM (Url.withUrlOptions $ \uo -> anyM (\u -> Url.checkBoth u (keySize key) uo) (keyUrls rmt key))
diff --git a/Remote/Helper/Chunked.hs b/Remote/Helper/Chunked.hs
--- a/Remote/Helper/Chunked.hs
+++ b/Remote/Helper/Chunked.hs
@@ -123,7 +123,7 @@
 	
 		loop bytesprocessed (chunk, bs) chunkkeys
 			| L.null chunk && numchunks > 0 = do
- 				-- Once all chunks are successfully
+				-- Once all chunks are successfully
 				-- stored, update the chunk log.
 				chunksStored u k (FixedSizeChunks chunksize) numchunks
 				return True
@@ -138,7 +138,7 @@
 					)
 		  where
 			numchunks = numChunks chunkkeys
- 			{- The MeterUpdate that is passed to the action
+			{- The MeterUpdate that is passed to the action
 			 - storing a chunk is offset, so that it reflects
 			 - the total bytes that have already been stored
 			 - in previous chunks. -}
@@ -290,7 +290,7 @@
 		hSeek h AbsoluteSeek startpoint
 		return h
 
- 	{- Progress meter updating is a bit tricky: If the Retriever
+	{- Progress meter updating is a bit tricky: If the Retriever
 	 - populates a file, it is responsible for updating progress
 	 - as the file is being retrieved. 
 	 -
diff --git a/Remote/Helper/Encryptable.hs b/Remote/Helper/Encryptable.hs
--- a/Remote/Helper/Encryptable.hs
+++ b/Remote/Helper/Encryptable.hs
@@ -58,7 +58,7 @@
 		Just "shared" -> use "encryption setup" . genSharedCipher
 			=<< highRandomQuality
 		-- hybrid encryption is the default when a keyid is
-                -- specified but no encryption
+		-- specified but no encryption
 		_ | maybe (M.member "keyid" c) (== "hybrid") encryption ->
 			use "encryption setup" . genEncryptedCipher key Hybrid
 				=<< highRandomQuality
@@ -88,10 +88,10 @@
 		(&&) (maybe True ( /= "false") $ M.lookup "highRandomQuality" c)
 			<$> fmap not (Annex.getState Annex.fast)
 	c' = foldr M.delete c
-                -- git-annex used to remove 'encryption' as well, since
-                -- it was redundant; we now need to keep it for
-                -- public-key encryption, hence we leave it on newer
-                -- remotes (while being backward-compatible).
+		-- git-annex used to remove 'encryption' as well, since
+		-- it was redundant; we now need to keep it for
+		-- public-key encryption, hence we leave it on newer
+		-- remotes (while being backward-compatible).
 		[ "keyid", "keyid+", "keyid-", "highRandomQuality" ]
 
 remoteCipher :: RemoteConfig -> Annex (Maybe Cipher)
diff --git a/Remote/Helper/Special.hs b/Remote/Helper/Special.hs
--- a/Remote/Helper/Special.hs
+++ b/Remote/Helper/Special.hs
@@ -87,7 +87,7 @@
 -- Use to acquire a resource when preparing a helper.
 resourcePrepare :: (Key -> (r -> Annex Bool) -> Annex Bool) -> (r -> helper) -> Preparer helper
 resourcePrepare withr helper k a = withr k $ \r ->
-        a (Just (helper r))
+	a (Just (helper r))
 
 -- A Storer that expects to be provided with a file containing
 -- the content of the key to store.
@@ -196,7 +196,7 @@
 	retrieveKeyFileGen k dest p enc =
 		safely $ prepareretriever k $ safely . go
 	  where
-	  	go (Just retriever) = displayprogress p k $ \p' ->
+		go (Just retriever) = displayprogress p k $ \p' ->
 			retrieveChunks retriever (uuid baser) chunkconfig
 				enck k dest p' (sink dest enc)
 		go Nothing = return False
@@ -210,7 +210,7 @@
 
 	checkPresentGen k enc = preparecheckpresent k go
 	  where
-	  	go (Just checker) = checkPresentChunks checker (uuid baser) chunkconfig enck k
+		go (Just checker) = checkPresentChunks checker (uuid baser) chunkconfig enck k
 		go Nothing = cantCheck baser
 		enck = maybe id snd enc
 
diff --git a/Remote/Hook.hs b/Remote/Hook.hs
--- a/Remote/Hook.hs
+++ b/Remote/Hook.hs
@@ -138,7 +138,7 @@
 	v <- lookupHook h action
 	liftIO $ check v
   where
-  	action = "checkpresent"
+	action = "checkpresent"
 	findkey s = key2file k `elem` lines s
 	check Nothing = error $ action ++ " hook misconfigured"
 	check (Just hook) = do
diff --git a/Remote/Rsync.hs b/Remote/Rsync.hs
--- a/Remote/Rsync.hs
+++ b/Remote/Rsync.hs
@@ -175,7 +175,7 @@
 			]
 		else return False
   where
- 	{- If the key being sent is encrypted or chunked, the file
+	{- If the key being sent is encrypted or chunked, the file
 	 - containing its content is a temp file, and so can be
 	 - renamed into place. Otherwise, the file is the annexed
 	 - object file, and has to be copied or hard linked into place. -}
diff --git a/Remote/S3.hs b/Remote/S3.hs
--- a/Remote/S3.hs
+++ b/Remote/S3.hs
@@ -104,19 +104,19 @@
 
 	archiveorg = do
 		showNote "Internet Archive mode"
-		void $ setRemoteCredPair noEncryptionUsed c (AWS.creds u) mcreds
+		c' <- setRemoteCredPair noEncryptionUsed c (AWS.creds u) mcreds
 		-- Ensure user enters a valid bucket name, since
 		-- this determines the name of the archive.org item.
 		let bucket = replace " " "-" $ map toLower $
 			fromMaybe (error "specify bucket=") $
-				getBucket c
+				getBucket c'
 		let archiveconfig = 
 			-- hS3 does not pass through x-archive-* headers
 			M.mapKeys (replace "x-archive-" "x-amz-") $
 			-- encryption does not make sense here
 			M.insert "encryption" "none" $
 			M.insert "bucket" bucket $
-			M.union c $
+			M.union c' $
 			-- special constraints on key names
 			M.insert "mungekeys" "ia" $
 			-- bucket created only when files are uploaded
diff --git a/Remote/Tahoe.hs b/Remote/Tahoe.hs
--- a/Remote/Tahoe.hs
+++ b/Remote/Tahoe.hs
@@ -167,7 +167,7 @@
 getSharedConvergenceSecret :: TahoeConfigDir -> IO SharedConvergenceSecret
 getSharedConvergenceSecret configdir = go (60 :: Int)
   where
-  	f = convergenceFile configdir
+	f = convergenceFile configdir
 	go n
 		| n == 0 = error $ "tahoe did not write " ++ f ++ " after 1 minute. Perhaps the daemon failed to start?"
 		| otherwise = do
@@ -190,7 +190,7 @@
 withTahoeConfigDir :: TahoeHandle -> (TahoeConfigDir -> IO a) -> IO a
 withTahoeConfigDir (TahoeHandle configdir v) a = go =<< atomically needsstart
   where
-  	go True = do
+	go True = do
 		startTahoeDaemon configdir
 		a configdir
 	go False = a configdir
diff --git a/Remote/Web.hs b/Remote/Web.hs
--- a/Remote/Web.hs
+++ b/Remote/Web.hs
@@ -120,7 +120,7 @@
 			Url.withUrlOptions $ catchMsgIO .
 				Url.checkBoth u' (keySize key)
   where
-  	firsthit [] miss _ = return miss
+	firsthit [] miss _ = return miss
 	firsthit (u:rest) _ a = do
 		r <- a u
 		case r of
diff --git a/RemoteDaemon/Transport/Ssh.hs b/RemoteDaemon/Transport/Ssh.hs
--- a/RemoteDaemon/Transport/Ssh.hs
+++ b/RemoteDaemon/Transport/Ssh.hs
@@ -119,5 +119,5 @@
 		| b2 > maxbackoff = maxbackoff
 		| otherwise = b2
 	  where
-	  	b2 = backoff * 2
+		b2 = backoff * 2
 		maxbackoff = 3600 -- one hour
diff --git a/RemoteDaemon/Types.hs b/RemoteDaemon/Types.hs
--- a/RemoteDaemon/Types.hs
+++ b/RemoteDaemon/Types.hs
@@ -20,7 +20,7 @@
 
 -- The URI of a remote is used to uniquely identify it (names change..)
 newtype RemoteURI = RemoteURI URI
-  deriving (Show)
+	deriving (Show)
 
 -- A Transport for a particular git remote consumes some messages
 -- from a Chan, and emits others to another Chan.
diff --git a/Test.hs b/Test.hs
--- a/Test.hs
+++ b/Test.hs
@@ -122,7 +122,7 @@
 #else
 		handleParseResult $ execParserPure pprefs pinfo args
 #endif
-  	progdesc = "git-annex test"
+	progdesc = "git-annex test"
 
 ingredients :: [Ingredient]
 ingredients =
@@ -822,7 +822,7 @@
 		 - be missing the content of the file that had
 		 - been put in it. -}
 		forM_ [r1, r2] $ \r -> indir testenv r $ do
-		 	git_annex testenv "get" [] @? "unable to get all files after merge conflict resolution in " ++ rname r
+			git_annex testenv "get" [] @? "unable to get all files after merge conflict resolution in " ++ rname r
 
 {- Simple case of conflict resolution; 2 different versions of annexed
  - file. -}
@@ -943,12 +943,12 @@
 		length v == 1
 			@? (what ++ " too many variant files in: " ++ show v)
 
- {- Check merge confalict resolution when a file is annexed in one repo,
-  - and checked directly into git in the other repo.
-  -
-  - This test requires indirect mode to set it up, but tests both direct and
-  - indirect mode.
-  -}
+{- Check merge confalict resolution when a file is annexed in one repo,
+ - and checked directly into git in the other repo.
+ -
+ - This test requires indirect mode to set it up, but tests both direct and
+ - indirect mode.
+ -}
 test_nonannexed_file_conflict_resolution :: TestEnv -> Assertion
 test_nonannexed_file_conflict_resolution testenv = do
 	check True False
@@ -957,7 +957,7 @@
 	check False True
   where
 	check inr1 switchdirect = withtmpclonerepo testenv False $ \r1 ->
-		withtmpclonerepo testenv False $ \r2 -> do
+		withtmpclonerepo testenv False $ \r2 ->
 			whenM (isInDirect r1 <&&> isInDirect r2) $ do
 				indir testenv r1 $ do
 					disconnectOrigin
@@ -1007,7 +1007,7 @@
 	check False True
   where
 	check inr1 switchdirect = withtmpclonerepo testenv False $ \r1 ->
-		withtmpclonerepo testenv False $ \r2 -> do
+		withtmpclonerepo testenv False $ \r2 ->
 			whenM (checkRepo (Types.coreSymlinks <$> Annex.getGitConfig) r1
 			       <&&> isInDirect r1 <&&> isInDirect r2) $ do
 				indir testenv r1 $ do
@@ -1094,9 +1094,9 @@
  - lost track of whether a file was a symlink. 
  -}
 test_conflict_resolution_symlink_bit :: TestEnv -> Assertion
-test_conflict_resolution_symlink_bit testenv = do
+test_conflict_resolution_symlink_bit testenv =
 	withtmpclonerepo testenv False $ \r1 ->
-		withtmpclonerepo testenv False $ \r2 -> do
+		withtmpclonerepo testenv False $ \r2 ->
 			withtmpclonerepo testenv False $ \r3 -> do
 				indir testenv r1 $ do
 					writeFile conflictor "conflictor"
@@ -1152,7 +1152,7 @@
 	not <$> git_annex testenv "uninit" [] @? "uninit failed to fail when git-annex branch was checked out"
 
 test_upgrade :: TestEnv -> Assertion
-test_upgrade testenv = intmpclonerepo testenv $ do
+test_upgrade testenv = intmpclonerepo testenv $
 	git_annex testenv "upgrade" [] @? "upgrade from same version failed"
 
 test_whereis :: TestEnv -> Assertion
@@ -1404,7 +1404,7 @@
 		, a
 		)
   where
-  	isdirect = annexeval $ do
+	isdirect = annexeval $ do
 		Annex.Init.initialize Nothing
 		Config.isDirect
 
diff --git a/Types/Crypto.hs b/Types/Crypto.hs
--- a/Types/Crypto.hs
+++ b/Types/Crypto.hs
@@ -59,10 +59,10 @@
 readMac _ = Nothing
 
 calcMac
-  :: Mac	  -- ^ MAC
-  -> L.ByteString -- ^ secret key
-  -> L.ByteString -- ^ message
-  -> String	  -- ^ MAC'ed message, in hexadecimals
+	:: Mac          -- ^ MAC
+	-> L.ByteString -- ^ secret key
+	-> L.ByteString -- ^ message
+	-> String       -- ^ MAC'ed message, in hexadecimal
 calcMac mac = case mac of
 	HmacSha1   -> showDigest $* hmacSha1
 	HmacSha224 -> showDigest $* hmacSha224
diff --git a/Types/Key.hs b/Types/Key.hs
--- a/Types/Key.hs
+++ b/Types/Key.hs
@@ -133,7 +133,7 @@
 	| normalfieldorder = maybe True (\k -> key2file k == f) (file2key f)
 	| otherwise = True
   where
-  	-- file2key will accept the fields in any order, so don't
+	-- file2key will accept the fields in any order, so don't
 	-- try the test unless the fields are in the normal order
 	normalfieldorder = fields `isPrefixOf` "smSC"
 	fields = map (f !!) $ filter (< length f) $ map succ $
diff --git a/Types/MetaData.hs b/Types/MetaData.hs
--- a/Types/MetaData.hs
+++ b/Types/MetaData.hs
@@ -290,4 +290,4 @@
 	, deserialize (serialize m') == Just m'
 	]
   where
-  	m' = removeEmptyFields m
+	m' = removeEmptyFields m
diff --git a/Types/ScheduledActivity.hs b/Types/ScheduledActivity.hs
--- a/Types/ScheduledActivity.hs
+++ b/Types/ScheduledActivity.hs
@@ -17,7 +17,7 @@
 data ScheduledActivity 
 	= ScheduledSelfFsck Schedule Duration
 	| ScheduledRemoteFsck UUID Schedule Duration
-  deriving (Eq, Read, Show, Ord)
+	deriving (Eq, Read, Show, Ord)
 
 {- Activities that run on a remote, within a time window, so
  - should be run when the remote gets connected. -}
diff --git a/Types/StandardGroups.hs b/Types/StandardGroups.hs
--- a/Types/StandardGroups.hs
+++ b/Types/StandardGroups.hs
@@ -96,7 +96,7 @@
 
 notArchived :: String
 notArchived = "not (copies=archive:1 or copies=smallarchive:1)"
-  	
+	
 {- Most repositories want any content that is only on untrusted
  - or dead repositories, or that otherwise does not have enough copies.
  - Does not look at .gitattributes since that is quite a lot slower.
diff --git a/Utility/Batch.hs b/Utility/Batch.hs
--- a/Utility/Batch.hs
+++ b/Utility/Batch.hs
@@ -32,7 +32,7 @@
 #if defined(linux_HOST_OS) || defined(__ANDROID__)
 batch a = wait =<< batchthread
   where
-  	batchthread = asyncBound $ do
+	batchthread = asyncBound $ do
 		setProcessPriority 0 maxNice
 		a
 #else
diff --git a/Utility/CoProcess.hs b/Utility/CoProcess.hs
--- a/Utility/CoProcess.hs
+++ b/Utility/CoProcess.hs
@@ -65,7 +65,7 @@
 			restartable s (receive $ coProcessFrom s)
 				return
   where
-  	restartable s a cont
+	restartable s a cont
 		| coProcessNumRestarts (coProcessSpec s) > 0 =
 			maybe restart cont =<< catchMaybeIO a
 		| otherwise = cont =<< a
@@ -87,7 +87,7 @@
 	raw $ coProcessTo s
 	return ch
   where
-  	raw h = do
+	raw h = do
 		fileEncoding h
 #ifdef mingw32_HOST_OS
 		hSetNewlineMode h noNewlineTranslation
diff --git a/Utility/CopyFile.hs b/Utility/CopyFile.hs
--- a/Utility/CopyFile.hs
+++ b/Utility/CopyFile.hs
@@ -47,10 +47,10 @@
 #ifndef mingw32_HOST_OS
 createLinkOrCopy src dest = go `catchIO` const fallback
   where
-  	go = do
+	go = do
 		createLink src dest
 		return True
-  	fallback = copyFileExternal CopyAllMetaData src dest
+	fallback = copyFileExternal CopyAllMetaData src dest
 #else
 createLinkOrCopy = copyFileExternal CopyAllMetaData
 #endif
diff --git a/Utility/Daemon.hs b/Utility/Daemon.hs
--- a/Utility/Daemon.hs
+++ b/Utility/Daemon.hs
@@ -175,7 +175,7 @@
 	cleanstale
 	return $ prefix ++ show pid ++ suffix
   where
-  	prefix = pidfile ++ "."
+	prefix = pidfile ++ "."
 	suffix = ".lck"
 	cleanstale = mapM_ (void . tryIO . removeFile) =<<
 		(filter iswinlockfile <$> dirContents (parentDir pidfile))
diff --git a/Utility/DataUnits.hs b/Utility/DataUnits.hs
--- a/Utility/DataUnits.hs
+++ b/Utility/DataUnits.hs
@@ -120,7 +120,7 @@
 
 	showUnit x (Unit size abbrev name) = s ++ " " ++ unit
 	  where
-	  	v = (fromInteger x :: Double) / fromInteger size
+		v = (fromInteger x :: Double) / fromInteger size
 		s = showImprecise 2 v
 		unit
 			| short = abbrev
diff --git a/Utility/Directory.hs b/Utility/Directory.hs
--- a/Utility/Directory.hs
+++ b/Utility/Directory.hs
@@ -56,7 +56,7 @@
 dirContentsRecursiveSkipping :: (FilePath -> Bool) -> Bool -> FilePath -> IO [FilePath]
 dirContentsRecursiveSkipping skipdir followsubdirsymlinks topdir = go [topdir]
   where
-  	go [] = return []
+	go [] = return []
 	go (dir:dirs)
 		| skipdir (takeFileName dir) = go dirs
 		| otherwise = unsafeInterleaveIO $ do
@@ -87,7 +87,7 @@
 dirTreeRecursiveSkipping :: (FilePath -> Bool) -> FilePath -> IO [FilePath]
 dirTreeRecursiveSkipping skipdir topdir = go [] [topdir]
   where
-  	go c [] = return c
+	go c [] = return c
 	go c (dir:dirs)
 		| skipdir (takeFileName dir) = go c dirs
 		| otherwise = unsafeInterleaveIO $ do
diff --git a/Utility/ExternalSHA.hs b/Utility/ExternalSHA.hs
--- a/Utility/ExternalSHA.hs
+++ b/Utility/ExternalSHA.hs
@@ -57,7 +57,7 @@
 			Left $ "Unexpected character in output of " ++ command ++ "\"" ++ sha ++ "\""
 		| otherwise = Right sha'
 	  where
-	  	sha' = map toLower sha
+		sha' = map toLower sha
 
 expectedSHALength :: Int -> Int
 expectedSHALength 1 = 40
diff --git a/Utility/FileSystemEncoding.hs b/Utility/FileSystemEncoding.hs
--- a/Utility/FileSystemEncoding.hs
+++ b/Utility/FileSystemEncoding.hs
@@ -111,7 +111,7 @@
 #ifndef mingw32_HOST_OS
 truncateFilePath n = go . reverse
   where
-  	go f =
+	go f =
 		let bytes = decodeW8 f
 		in if length bytes <= n
 			then reverse f
diff --git a/Utility/Format.hs b/Utility/Format.hs
--- a/Utility/Format.hs
+++ b/Utility/Format.hs
@@ -117,7 +117,7 @@
 	handle (x:'x':n1:n2:rest)
 		| isescape x && allhex = (fromhex, rest)
 	  where
-	  	allhex = isHexDigit n1 && isHexDigit n2
+		allhex = isHexDigit n1 && isHexDigit n2
 		fromhex = [chr $ readhex [n1, n2]]
 		readhex h = Prelude.read $ "0x" ++ h :: Int
 	handle (x:n1:n2:n3:rest)
diff --git a/Utility/Gpg.hs b/Utility/Gpg.hs
--- a/Utility/Gpg.hs
+++ b/Utility/Gpg.hs
@@ -166,7 +166,7 @@
 secretKeys = catchDefaultIO M.empty makemap
   where
 	makemap = M.fromList . parse . lines <$> readStrict params
-  	params = [Params "--with-colons --list-secret-keys --fixed-list-mode"]
+	params = [Params "--with-colons --list-secret-keys --fixed-list-mode"]
 	parse = extract [] Nothing . map (split ":")
 	extract c (Just keyid) (("uid":_:_:_:_:_:_:_:_:userid:_):rest) =
 		extract ((keyid, decode_c userid):c) Nothing rest
@@ -196,7 +196,7 @@
 	withHandle StdinHandle createProcessSuccess (proc gpgcmd params) feeder
   where
 	params = ["--batch", "--gen-key"]
-  	feeder h = do
+	feeder h = do
 		hPutStr h $ unlines $ catMaybes
 			[ Just $  "Key-Type: " ++ 
 				case keytype of
@@ -232,7 +232,7 @@
 	randomquality :: Int
 	randomquality = if highQuality then 2 else 1
 
- 	{- The size is the number of bytes of entropy desired; the data is
+	{- The size is the number of bytes of entropy desired; the data is
 	 - base64 encoded, so needs 8 bits to represent every 6 bytes of
 	 - entropy. -}
 	expectedlength = size * 8 `div` 6
diff --git a/Utility/HumanTime.hs b/Utility/HumanTime.hs
--- a/Utility/HumanTime.hs
+++ b/Utility/HumanTime.hs
@@ -27,7 +27,7 @@
 import qualified Data.Map as M
 
 newtype Duration = Duration { durationSeconds :: Integer }
-  deriving (Eq, Ord, Read, Show)
+	deriving (Eq, Ord, Read, Show)
 
 durationSince :: UTCTime -> IO Duration
 durationSince pasttime = do
@@ -47,8 +47,8 @@
 parseDuration :: String -> Maybe Duration
 parseDuration = Duration <$$> go 0
   where
-  	go n [] = return n
-  	go n s = do
+	go n [] = return n
+	go n s = do
 		num <- readish s :: Maybe Integer
 		case dropWhile isDigit s of
 			(c:rest) -> do
diff --git a/Utility/InodeCache.hs b/Utility/InodeCache.hs
--- a/Utility/InodeCache.hs
+++ b/Utility/InodeCache.hs
@@ -182,7 +182,7 @@
 		SentinalStatus (not unchanged) tsdelta
 	  where
 #ifdef mingw32_HOST_OS
-	  	unchanged = oldinode == newinode && oldsize == newsize
+		unchanged = oldinode == newinode && oldsize == newsize
 		tsdelta = TSDelta $ do
 			-- Run when generating an InodeCache, 
 			-- to get the current delta.
diff --git a/Utility/Matcher.hs b/Utility/Matcher.hs
--- a/Utility/Matcher.hs
+++ b/Utility/Matcher.hs
@@ -90,7 +90,7 @@
 tokenGroups [] = []
 tokenGroups (t:ts) = go t
   where
-  	go Open =
+	go Open =
 		let (gr, rest) = findClose ts
 		in gr : tokenGroups rest
 	go Close = tokenGroups ts -- not picky about missing Close
@@ -101,7 +101,7 @@
 	let (g, rest) = go [] l
 	in (Group (reverse g), rest)
   where
-  	go c [] = (c, []) -- not picky about extra Close
+	go c [] = (c, []) -- not picky about extra Close
 	go c (t:ts) = dispatch t
 	  where
 		dispatch Close = (c, ts)
diff --git a/Utility/Path.hs b/Utility/Path.hs
--- a/Utility/Path.hs
+++ b/Utility/Path.hs
@@ -235,11 +235,11 @@
 	| null drive = recombine parts
 	| otherwise = recombine $ "/cygdrive" : driveletter drive : parts
   where
-  	(drive, p') = splitDrive p
+	(drive, p') = splitDrive p
 	parts = splitDirectories p'
-  	driveletter = map toLower . takeWhile (/= ':')
+	driveletter = map toLower . takeWhile (/= ':')
 	recombine = fixtrailing . Posix.joinPath
-  	fixtrailing s
+	fixtrailing s
 		| hasTrailingPathSeparator p = Posix.addTrailingPathSeparator s
 		| otherwise = s
 #endif
@@ -272,7 +272,7 @@
 sanitizeFilePath :: String -> FilePath
 sanitizeFilePath = map sanitize
   where
-  	sanitize c
+	sanitize c
 		| c == '.' = c
 		| isSpace c || isPunctuation c || isSymbol c || isControl c || c == '/' = '_'
 		| otherwise = c
diff --git a/Utility/Quvi.hs b/Utility/Quvi.hs
--- a/Utility/Quvi.hs
+++ b/Utility/Quvi.hs
@@ -113,7 +113,7 @@
 supported Quvi09 url = (firstlevel <&&> secondlevel)
 		`catchNonAsync` (\_ -> return False)
   where
-  	firstlevel = case uriAuthority =<< parseURIRelaxed url of
+	firstlevel = case uriAuthority =<< parseURIRelaxed url of
 		Nothing -> return False
 		Just auth -> do
 			let domain = map toLower $ uriRegName auth
diff --git a/Utility/Rsync.hs b/Utility/Rsync.hs
--- a/Utility/Rsync.hs
+++ b/Utility/Rsync.hs
@@ -57,7 +57,7 @@
 rsyncParamsFixup :: [CommandParam] -> [CommandParam]
 rsyncParamsFixup = map fixup
   where
-  	fixup (File f) = File (toCygPath f)
+	fixup (File f) = File (toCygPath f)
 	fixup p = p
 
 {- Runs rsync, but intercepts its progress output and updates a meter.
diff --git a/Utility/SRV.hs b/Utility/SRV.hs
--- a/Utility/SRV.hs
+++ b/Utility/SRV.hs
@@ -74,7 +74,7 @@
 		maybe [] use r
 #endif
   where
-  	use = orderHosts . map tohosts
+	use = orderHosts . map tohosts
 	tohosts (priority, weight, port, hostname) =
 		( (priority, weight)
 		, (B8.toString hostname, PortNumber $ fromIntegral port)
diff --git a/Utility/Scheduled.hs b/Utility/Scheduled.hs
--- a/Utility/Scheduled.hs
+++ b/Utility/Scheduled.hs
@@ -44,7 +44,7 @@
 
 {- Some sort of scheduled event. -}
 data Schedule = Schedule Recurrance ScheduledTime
-  deriving (Eq, Read, Show, Ord)
+	deriving (Eq, Read, Show, Ord)
 
 data Recurrance
 	= Daily
@@ -54,7 +54,7 @@
 	| Divisible Int Recurrance
 	-- ^ Days, Weeks, or Months of the year evenly divisible by a number.
 	-- (Divisible Year is years evenly divisible by a number.)
-  deriving (Eq, Read, Show, Ord)
+	deriving (Eq, Read, Show, Ord)
 
 type WeekDay = Int
 type MonthDay = Int
@@ -63,7 +63,7 @@
 data ScheduledTime
 	= AnyTime
 	| SpecificTime Hour Minute
-  deriving (Eq, Read, Show, Ord)
+	deriving (Eq, Read, Show, Ord)
 
 type Hour = Int
 type Minute = Int
@@ -73,7 +73,7 @@
 data NextTime
 	= NextTimeExactly LocalTime
 	| NextTimeWindow LocalTime LocalTime
-  deriving (Eq, Read, Show)
+	deriving (Eq, Read, Show)
 
 startTime :: NextTime -> LocalTime
 startTime (NextTimeExactly t) = t
@@ -96,9 +96,9 @@
 			NextTimeExactly t -> window (localDay t) (localDay t)
 	| otherwise = NextTimeExactly . startTime <$> findfromtoday False
   where
-  	findfromtoday anytime = findfrom recurrance afterday today
+	findfromtoday anytime = findfrom recurrance afterday today
 	  where
-	  	today = localDay currenttime
+		today = localDay currenttime
 		afterday = sameaslastrun || toolatetoday
 		toolatetoday = not anytime && localTimeOfDay currenttime >= nexttime
 		sameaslastrun = lastrun == Just today
@@ -163,8 +163,8 @@
 		Divisible n r'@(Yearly _) -> handlediv n r' ynum Nothing
 		Divisible _ r'@(Divisible _ _) -> findfrom r' afterday candidate
 	  where
-	  	skip n = findfrom r False (addDays n candidate)
-	  	handlediv n r' getval mmax
+		skip n = findfrom r False (addDays n candidate)
+		handlediv n r' getval mmax
 			| n > 0 && maybe True (n <=) mmax =
 				findfromwhere r' (divisible n . getval) afterday candidate
 			| otherwise = Nothing
@@ -267,7 +267,7 @@
 	constructor u
 		| "s" `isSuffixOf` u = constructor $ reverse $ drop 1 $ reverse u
 		| otherwise = Nothing
-  	withday sd u = do
+	withday sd u = do
 		c <- constructor u
 		d <- readish sd
 		Just $ c (Just d)
@@ -285,7 +285,7 @@
 fromScheduledTime (SpecificTime h m) = 
 	show h' ++ (if m > 0 then ":" ++ pad 2 (show m) else "") ++ " " ++ ampm
   where
-  	pad n s = take (n - length s) (repeat '0') ++ s
+	pad n s = take (n - length s) (repeat '0') ++ s
 	(h', ampm)
 		| h == 0 = (12, "AM")
 		| h < 12 = (h, "AM")
@@ -304,10 +304,10 @@
 	(s:[]) -> go s id
 	_ -> Nothing
   where
-  	h0 h
+	h0 h
 		| h == 12 = 0
 		| otherwise = h
-  	go :: String -> (Int -> Int) -> Maybe ScheduledTime
+	go :: String -> (Int -> Int) -> Maybe ScheduledTime
 	go s adjust =
 		let (h, m) = separate (== ':') s
 		in SpecificTime
@@ -363,7 +363,7 @@
 				]
 		]
 	  where
-	  	arbday = oneof
+		arbday = oneof
 			[ Just <$> nonNegative arbitrary
 			, pure Nothing
 			]
diff --git a/Utility/SshConfig.hs b/Utility/SshConfig.hs
--- a/Utility/SshConfig.hs
+++ b/Utility/SshConfig.hs
@@ -56,7 +56,7 @@
 		| iscomment l = hoststanza host c ((Left $ mkcomment l):hc) ls
 		| otherwise = case splitline l of
 			(indent, k, v)
-			 	| isHost k -> hoststanza v
+				| isHost k -> hoststanza v
 					(HostConfig host (reverse hc):c) [] ls
 				| otherwise -> hoststanza host c
 					((Right $ SshSetting indent k v):hc) ls
@@ -87,7 +87,7 @@
 findHostConfigKey :: SshConfig -> Key -> Maybe Value
 findHostConfigKey (HostConfig _ cs) wantk = go (rights cs) (map toLower wantk)
   where
-  	go [] _ = Nothing
+	go [] _ = Nothing
 	go ((SshSetting _ k v):rest) wantk'
 		| map toLower k == wantk' = Just v
 		| otherwise = go rest wantk'
@@ -98,7 +98,7 @@
 addToHostConfig (HostConfig host cs) k v = 
 	HostConfig host $ Right (SshSetting indent k v) : cs
   where
- 	{- The indent is taken from any existing SshSetting
+	{- The indent is taken from any existing SshSetting
 	 - in the HostConfig (largest indent wins). -}
 	indent = fromMaybe "\t" $ headMaybe $ reverse $
 		sortBy (comparing length) $ map getindent cs
diff --git a/Utility/TList.hs b/Utility/TList.hs
--- a/Utility/TList.hs
+++ b/Utility/TList.hs
@@ -57,7 +57,7 @@
 	unless (emptyDList dl') $
 		putTMVar tlist dl'
   where
-  	emptyDList = D.list True (\_ _ -> False)
+	emptyDList = D.list True (\_ _ -> False)
 
 consTList :: TList a -> a -> STM ()
 consTList tlist v = modifyTList tlist $ \dl -> D.cons v dl
diff --git a/Utility/WebApp.hs b/Utility/WebApp.hs
--- a/Utility/WebApp.hs
+++ b/Utility/WebApp.hs
@@ -117,7 +117,7 @@
 	when (isJust h) $
 		error "getSocket with HostName not supported on this OS"
 	addr <- inet_addr "127.0.0.1"
- 	sock <- socket AF_INET Stream defaultProtocol
+	sock <- socket AF_INET Stream defaultProtocol
 	preparesocket sock
 	bindSocket sock (SockAddrInet aNY_PORT addr)
 	use sock
diff --git a/Utility/Yesod.hs b/Utility/Yesod.hs
--- a/Utility/Yesod.hs
+++ b/Utility/Yesod.hs
@@ -25,10 +25,11 @@
 
 #if MIN_VERSION_yesod(1,2,0)
 import Yesod as Y
+import Yesod.Form.Bootstrap3 as Y hiding (bfs)
 #else
 import Yesod as Y hiding (Html)
-#endif
 import Assistant.WebApp.Bootstrap3 as Y hiding (bfs)
+#endif
 #ifndef __NO_TH__
 import Yesod.Default.Util
 import Language.Haskell.TH.Syntax (Q, Exp)
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+git-annex (5.20141013) unstable; urgency=medium
+
+  * Adjust cabal file to support building w/o assistant on the hurd.
+  * Support building with yesod 1.4.
+  * S3: Fix embedcreds=yes handling for the Internet Archive.
+  * map: Handle .git prefixed remote repos. Closes: #614759
+  * repair: Prevent auto gc from happening when fetching from a remote.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 13 Oct 2014 10:13:06 -0400
+
 git-annex (5.20140927) unstable; urgency=medium
 
   * Really depend (not just build-depend) on new enough git for --no-gpg-sign
diff --git a/debian/control b/debian/control
--- a/debian/control
+++ b/debian/control
@@ -108,10 +108,15 @@
  dealing with files larger than git can currently easily handle, whether due
  to limitations in memory, time, or disk space.
  .
- Even without file content tracking, being able to manage files with git,
- move files around and delete files with versioned directory trees, and use
- branches and distributed clones, are all very handy reasons to use git. And
- annexed files can co-exist in the same git repository with regularly
- versioned files, which is convenient for maintaining documents, Makefiles,
- etc that are associated with annexed files but that benefit from full
- revision control.
+ It can store large files in many places, from local hard drives, to a
+ large number of cloud storage services, including S3, WebDAV,
+ and rsync, with a dozen cloud storage providers usable via plugins.
+ Files can be stored encrypted with gpg, so that the cloud storage
+ provider cannot see your data. git-annex keeps track of where each file
+ is stored, so it knows how many copies are available, and has many
+ facilities to ensure your data is preserved.
+ .
+ git-annex can also be used to keep a folder in sync between computers,
+ noticing when files are changed, and automatically committing them
+ to git and transferring them to other computers. The git-annex webapp
+ makes it easy to set up and use git-annex this way.
diff --git a/debian/copyright b/debian/copyright
--- a/debian/copyright
+++ b/debian/copyright
@@ -28,6 +28,10 @@
 Copyright: © 2010-2014 Joey Hess <joey@kitenet.net>
 License: GPL-3+
 
+Files: Assistant/WebApp/Bootstrap3.hs
+Copyright: 2010 Michael Snoyman
+License: BSD-2-clause
+
 Files: doc/logo* */favicon.ico standalone/osx/git-annex.app/Contents/Resources/git-annex.icns standalone/android/icons/*
 Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>
            2010 Joey Hess <joey@kitenet.net>
diff --git a/doc/bugs/Drop_files_with_the_same_checksum..mdwn b/doc/bugs/Drop_files_with_the_same_checksum..mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/Drop_files_with_the_same_checksum..mdwn
@@ -0,0 +1,33 @@
+### Please describe the problem.
+When two identical files are annexed and one of them is dropped, both files are gone (one dangling symlink is left). This may be intentional (the checksums are the same after all), but then is there a way to drop one of the files?
+
+### What steps will reproduce the problem?
+
+    mkdir annex
+    cd annex
+    git init
+    git annex init
+    mkdir a b
+    dd if=/dev/urandom of=a/data.bin count=2048
+    cp a/data.bin b
+    git annex add a/data.bin b/data.bin
+    git commit -m "Added raw data."
+    git annex drop --force a/data.bin
+    file b/data.bin
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 5.20140831+b1  
+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  
+
+Distributor ID: Debian  
+Description:    Debian GNU/Linux testing (jessie)  
+Release:        testing  
+Codename:       jessie  
+
+> If you don't want git-annex to de-duplicate files you can use a backend
+> such as WORM. Here it's behaving as expected, so [[done]]. --[[Joey]]
diff --git a/doc/bugs/Upload_to_S3_fails_.mdwn b/doc/bugs/Upload_to_S3_fails_.mdwn
--- a/doc/bugs/Upload_to_S3_fails_.mdwn
+++ b/doc/bugs/Upload_to_S3_fails_.mdwn
@@ -55,3 +55,5 @@
 3%       858.1KB/s 6h45mmux_client_request_session: read from master failed: Broken pipe
 
 """]]
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/annex_get_fails_from_read-only_filesystem.mdwn b/doc/bugs/annex_get_fails_from_read-only_filesystem.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/annex_get_fails_from_read-only_filesystem.mdwn
@@ -0,0 +1,24 @@
+### Please describe the problem.
+
+annex get does not work from read-only file systems...
+
+### What steps will reproduce the problem?
+
+    $ git annex get --from=...
+    error: could not lock config file /.../Annex/.git/config: Read-only file system
+    get ... (from ...) error: could not lock config file .../Annex/.git/config: Read-only file system
+      git [Param "config",Param "annex.version",Param "5"] failed
+    failed
+
+### What version of git-annex are you using? On what operating system?
+
+annex.version = 3 in the remote
+
+    $ git annex version
+    git-annex version: 5.20140927
+    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
diff --git a/doc/bugs/git_annex_add_adds_unlocked_files.mdwn b/doc/bugs/git_annex_add_adds_unlocked_files.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/git_annex_add_adds_unlocked_files.mdwn
@@ -0,0 +1,21 @@
+### Please describe the problem.
+
+git annex add . should ignore unlocked files
+
+### What steps will reproduce the problem?
+SEE NEXT COMMENT
+
+### What version of git-annex are you using? On what operating system?
+
+
+### 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.
+"""]]
+
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/git_clone_ignores_annex.mdwn b/doc/bugs/git_clone_ignores_annex.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/git_clone_ignores_annex.mdwn
@@ -0,0 +1,25 @@
+### Please describe the problem.
+
+More of a feature request than a bug. It would be nice if when creating a local clone with git clone this would run automatically:
+
+ln -s ../../annex/.git/annex .git/annex
+
+to hook up the annex. Just a minor thing, but I'd be nice.
+
+### What steps will reproduce the problem?
+
+
+### What version of git-annex are you using? On what operating system?
+
+
+### 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.
+"""]]
+
+> [[done]] --[[Joey]] 
diff --git a/doc/bugs/modified_permissions_persist_after_unlock__44___commit.mdwn b/doc/bugs/modified_permissions_persist_after_unlock__44___commit.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/bugs/modified_permissions_persist_after_unlock__44___commit.mdwn
@@ -0,0 +1,40 @@
+### Please describe the problem.
+
+Modifying an annexed file with unlock then commit leaves the link with permissions 777 and git status reports a typechange, which makes checkout impossible. Resolves by running git unlock on the file.
+
+### What steps will reproduce the problem?
+
+echo foo > test.txt
+git annex add test.txt
+git commit -a -m "first"
+git annex unlock test.txt
+echo foobar > test.txt
+git commit -a -m "second"
+
+git status (notice typechange message)
+
+git unlock test.txt (corrects and retains both versions)
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 3.20120406
+local repository version: 3
+default repository version: 3
+supported repository versions: 3
+upgrade supported from repository versions: 0 1 2
+
+git version 1.7.9.5
+
+
+### 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.
+"""]]
+
+[[!tag confirmed]]
+[[!meta title="git commit of unlocked file leaves typechange staged in index"]]
diff --git a/doc/design/metadata/comment_7_04cd255a516c8520a7bc1a8fad253533._comment b/doc/design/metadata/comment_7_04cd255a516c8520a7bc1a8fad253533._comment
new file mode 100644
--- /dev/null
+++ b/doc/design/metadata/comment_7_04cd255a516c8520a7bc1a8fad253533._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlM_DRhi_5pJrTA0HbApHR25iAgy-NBXTY"
+ nickname="Tor Arne"
+ subject="comment 7"
+ date="2014-10-01T22:43:40Z"
+ content="""
+I have the same question as Toby, is there a particular reason the whole timestamp is not stored?
+"""]]
diff --git a/doc/design/metadata/comment_8_0a7e55e7626f72f63966fa1e1d2cf100._comment b/doc/design/metadata/comment_8_0a7e55e7626f72f63966fa1e1d2cf100._comment
new file mode 100644
--- /dev/null
+++ b/doc/design/metadata/comment_8_0a7e55e7626f72f63966fa1e1d2cf100._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlM_DRhi_5pJrTA0HbApHR25iAgy-NBXTY"
+ nickname="Tor Arne"
+ subject="Can tags/metadata be used for preferred content?"
+ date="2014-10-01T22:45:36Z"
+ content="""
+Would love to be able to \"tag\" something as archived instead of moving it into a special folder. Coupled with a FinderSync extension on OS X Yosemite for right-click menu. This would allow me to also \"view\" the archive and bring things out of there by \"untagging\" it, if I understand the feature correctly?
+"""]]
diff --git a/doc/design/metadata/comment_9_f0bb62c885a925e0da5ae8ce3c5e9003._comment b/doc/design/metadata/comment_9_f0bb62c885a925e0da5ae8ce3c5e9003._comment
new file mode 100644
--- /dev/null
+++ b/doc/design/metadata/comment_9_f0bb62c885a925e0da5ae8ce3c5e9003._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlM_DRhi_5pJrTA0HbApHR25iAgy-NBXTY"
+ nickname="Tor Arne"
+ subject="comment 9"
+ date="2014-10-01T23:35:39Z"
+ content="""
+Sorry for the noise, I see that tags _can_ be used for preferred content, excellent!
+
+But it seems metadata is tied to a key, not to a specific file/path. If I have 10 different files all with the same content (for some reason, say a simple txt file, Gemspec, or something), and I want to tag one of them as important, it doesn't mean they all are :o
+"""]]
diff --git a/doc/design/requests_routing/simroutes.hs b/doc/design/requests_routing/simroutes.hs
--- a/doc/design/requests_routing/simroutes.hs
+++ b/doc/design/requests_routing/simroutes.hs
@@ -182,7 +182,7 @@
 		, satisfiedRequests = satisfiedRequests' `S.union` checkSatisfied wantFiles' haveFiles'
 		}
 	  where
-	  	wantFiles' = foldr addRequest (wantFiles r1) (wantFiles r2)
+		wantFiles' = foldr addRequest (wantFiles r1) (wantFiles r2)
 		haveFiles' = S.foldr (addFile wantFiles' satisfiedRequests') (haveFiles r1) (haveFiles r2)
 		satisfiedRequests' = satisfiedRequests r1 `S.union` satisfiedRequests r2
 
@@ -229,7 +229,7 @@
 
 mkTransfer :: (RandomGen g) => [NodeName] -> Rand g TransferNode
 mkTransfer immobiles = do
-  	-- Transfer nodes are given random routes. May be simplistic.
+	-- Transfer nodes are given random routes. May be simplistic.
 	-- Also, some immobile nodes will not be serviced by any transfer nodes.
 	numpossiblelocs <- getRandomR transferDestinationsRange
 	possiblelocs <- sequence (replicate numpossiblelocs (randomfrom immobiles))
@@ -283,7 +283,7 @@
 	--, ("Immobile nodes at end", show is)
 	]
   where
-  	findoriginreqs = filter (\r -> requestTTL r == originTTL)
+	findoriginreqs = filter (\r -> requestTTL r == originTTL)
 	findunsatisfied r = 
 		let wantedfs = S.fromList $ map requestedFile (findoriginreqs (wantFiles r))
 		in S.difference wantedfs (haveFiles r)
diff --git a/doc/devblog/day_222_preparing_for_debian_release.mdwn b/doc/devblog/day_222_preparing_for_debian_release.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/devblog/day_222_preparing_for_debian_release.mdwn
@@ -0,0 +1,12 @@
+Made two releases of git-annex, yesterday and today, which turned out to
+contain only Debian changes. So no need for other users to upgrade.
+
+This included fixing building on mips, and arm architectures.
+The mips build was running out of memory, and I was able to work around
+that. Then the arm builds broke today, because of a recent change to the
+version of llvm that has completely trashed ghc. Luckily, I was able
+to work around that too.
+
+Hopefully that will get last week's security fix into Debian testing,
+and otherwise have git-annex in Debian in good shape for the upcoming
+freeze.
diff --git a/doc/devblog/day_223__partial_commit_problem.mdwn b/doc/devblog/day_223__partial_commit_problem.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/devblog/day_223__partial_commit_problem.mdwn
@@ -0,0 +1,26 @@
+`git commit $some_unlocked_file` seems like a reasonably common thing for
+someone to do, so it's surprising to find that it's a [[little bit broken|/bugs/modified_permissions_persist_after_unlock__44___commit]],
+leaving the file staged in the index after (correctly) committing the
+annexed symlink.
+
+This is caused by either a bug in git and/or by git-annex abusing the
+git post-commit hook to do something it shouldn't do, although it's not
+unique in using the post-commit hook this way. I'm talking this over with
+Junio, and the fix will depend on the result of that conversation. It might
+involve git-annex detecting this case and canceling the commit, asking the
+user to `git annex add` the file first. Or it might involve a new git hook,
+although I have not had good luck getting hooks added to git before.
+
+----
+
+Meanwhile, today I did some other bug fixing. Fixed the Internet Archive
+support for embedcreds=yes. Made `git annex map` work for remote repos
+in a directory with an implicit ".git" prefix. And fixed a
+strange problem where the repository repair code caused a `git gc` to run
+and then tripped over its pid file.
+
+I seem to have enough fixes to make another release pretty soon.
+Especially since the current release of git-annex doesn't build with yesod
+1.4.
+
+Backlog: 94 messages
diff --git a/doc/direct_mode/comment_15_599b2285d24ae1244a1945d572b2c397._comment b/doc/direct_mode/comment_15_599b2285d24ae1244a1945d572b2c397._comment
new file mode 100644
--- /dev/null
+++ b/doc/direct_mode/comment_15_599b2285d24ae1244a1945d572b2c397._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmjjrCHEIa4vpDIJoBuJsrF3y8wZQElVHw"
+ nickname="Siyuan"
+ subject="Non-direct mode for Windows"
+ date="2014-10-08T15:55:04Z"
+ content="""
+Why Windows is restricted to direct mode? NTFS has symbolic links too. Is that fundamentally different from POSIX symlinks that it cannot be done?
+"""]]
diff --git a/doc/forum/.mdwn b/doc/forum/.mdwn
deleted file mode 100644
--- a/doc/forum/.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-http://stackoverflow.com/questions/26041704/removing-repository-in-git-annex
-
-Does anyone know a solution for this?
diff --git a/doc/forum/Broken_symlinks_remain_after_drop.mdwn b/doc/forum/Broken_symlinks_remain_after_drop.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Broken_symlinks_remain_after_drop.mdwn
@@ -0,0 +1,7 @@
+This is a newb question. I don't know whether this is a bug or the way git-annex is intended to function.
+
+I have two annex repos connected to each other. My idea was to have the first repository add files, which would then be moved to the second repository for storage. After moving, repo1 would be empty again, empty and clean of any symlinks.
+
+But after I 'git-annex move * --to repo2' broken symlinks remain in repo1. I don't want any broken/unused symlinks to remain in repo1 for object data it doesn't currently have (even if those files remain in the repository itself).
+
+Is there a way I can clean/remove broken symlinks to object data when those objects aren't present, so the directory only contains symlinks when the repo currently has the object data for those files?
diff --git a/doc/forum/Equivalent_to_git_bundle__63__.mdwn b/doc/forum/Equivalent_to_git_bundle__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Equivalent_to_git_bundle__63__.mdwn
@@ -0,0 +1,10 @@
+Hi,
+
+git provides a neat way to create archives of git repos (or parts thereof): git bundle.
+
+git bundle obviously works with git annex as well, BUT those bundles don't include the actual content (in other words, only the symlinks are bundled up).
+
+Is there a way to get the git bundle functionality with git annex?
+
+THX & Cheers,
+Toby.
diff --git a/doc/forum/Git_annex_hangs.mdwn b/doc/forum/Git_annex_hangs.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Git_annex_hangs.mdwn
@@ -0,0 +1,2 @@
+http://stackoverflow.com/questions/26305691/git-annex-hangs
+Does anyone know what might be causing this?
diff --git a/doc/forum/How_To_Permanently_Delete_a_File__63__.mdwn b/doc/forum/How_To_Permanently_Delete_a_File__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/How_To_Permanently_Delete_a_File__63__.mdwn
@@ -0,0 +1,13 @@
+Hi,
+
+We have several large git annex repos where all of the files are on remotes and we want to got through and clean up the repositories by deleting some subset of files.
+
+What is the fastest way to permanently delete files from a git annex repository with remotes?
+
+I guess I can to ``git annex drop --numcopies=0 <file>; git rm <file>``. Does that actually delete the file permanently?
+
+Is there a faster way?
+
+Thanks,
+
+Mike
diff --git a/doc/forum/How_to_list_all_existing_metadata_types__63__.mdwn b/doc/forum/How_to_list_all_existing_metadata_types__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/How_to_list_all_existing_metadata_types__63__.mdwn
@@ -0,0 +1,15 @@
+Is there any way to list all of the existing tag and metadata field types? What I mean is, I have files tagged with several different tags, files with several metadata fields; is there any way to list all the tag and field names being used (not all the files WITH those tags)?
+
+For example, something like:
+
+    git annex metadata --listfields
+    lastchanged
+    month
+    month-lastchanged
+    year
+    year-lastchanged
+
+    git annex metadata --listtags
+    Public
+    Personal
+    Work
diff --git a/doc/forum/Preserving_extended_attributes.mdwn b/doc/forum/Preserving_extended_attributes.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/Preserving_extended_attributes.mdwn
@@ -0,0 +1,5 @@
+Hey,
+
+I was wondering if it is currently possible to let the assistant (or git-annex in general) preserve extended attributes. I didn't find any options hinting at this, although it should be possible at least in theory by using the metadata system of git-annex...
+
+Considering that some applications use extended attributes to store custom meta data (like tags etc.), I think it would be valuable to have such an option...
diff --git a/doc/forum/add_only_binary_files__63__.mdwn b/doc/forum/add_only_binary_files__63__.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/add_only_binary_files__63__.mdwn
@@ -0,0 +1,1 @@
+Is there a way to only add binary files with git annex add command?
diff --git a/doc/forum/files_being_dropped_undesirably.mdwn b/doc/forum/files_being_dropped_undesirably.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/files_being_dropped_undesirably.mdwn
@@ -0,0 +1,47 @@
+I currently am using 3 repositories for my personal annex, and on each of them I'm running the assistant (they are normal git annex repositories). However all my files are migrating to my work desktop. My other two repositories seem to keep dropping them.
+
+Last night on my laptop I did a "git annex get *" to pull _all_ the files onto it. I saw in the .git/annex/daemon.log that each file was being dropped as soon as it was gotten. The output of "git annex get" showed files being transfered across, and the .git/annex/daemon.log showed files being dropped straight away. Currently I'd like to keep all my files on all my repositories (and perhaps later I'll revise that).
+
+Could someone please help me understand why annex is dropping my files, and what I could do to keep them on all my repositories?
+
+Here is the output of a get for a single file:
+
+    ~/Documents/personal-annex $ git annex get 2014/09/15/IMG_1123.JPG
+    get 2014/09/15/IMG_1123.JPG (from pea15.local_Documents_annexpersonal...)
+    SHA256E-s1841221--deeaa13935907ad606f941397bb57432c1eccfd5c361b8c16d2b19bfbe8437a6.JPG
+          1,841,221 100%   11.40MB/s    0:00:00 (xfr#1, to-chk=0/1)
+    ok
+    (Recording state in git...)
+
+
+Here is the corresponding daemon.log output:
+
+    [2014-10-09 09:11:34 AEDT] Committer: Committing changes to git
+    [2ok
+    (Recording state in git...)
+    (Recording state in git...)
+    (Recording state in git...)
+    drop 2014/09/15/IMG_1123.JPG 01(checking pea15.local_Documents_annexpersonal...) 4-10-09 09:11:34 AEDT] Pusher: Syncing with pea15.local_Documents_annexpersonal 
+    [2014-10-09 09:11:35 AEDT] Committer: Committing changes to git
+    To ssh://geoffc@git-annex-pea-15-geoffc_Documents.2Fannex.2Dpersonal/~/Documents/annex-personal/
+       04742c0..d1a5a36  git-annex -> synced/git-annex
+    [2014-10-09 09:11:38 AEDT] Pusher: Syncing with pea15.local_Documents_annexpersonal 
+    Everything up-to-date
+
+
+And here is a snippet from my .git/config:
+
+    [annex]
+            uuid = 57c4e6d1-0c6b-4c49-a235-4119d3864c14
+            version = 5
+            direct = true
+            #diskreserve = 2 gigabyte
+            autoupgrade = ask
+            debug = false
+            expireunused = false
+            autocommit = true
+    [remote "pea15.local_Documents_annexpersonal"]
+            url = ssh://geoffc@git-annex-pea-15-geoffc_Documents.2Fannex.2Dpersonal/~/Documents/annex-personal/
+            fetch = +refs/heads/*:refs/remotes/pea15.local_Documents_annexpersonal/*
+            annex-uuid = 2ef6bbfe-662f-48ba-aa52-8e2f82bcfb15
+            annex-cost = 175.0
diff --git a/doc/forum/using_git-annex_with_lightroom.mdwn b/doc/forum/using_git-annex_with_lightroom.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/forum/using_git-annex_with_lightroom.mdwn
@@ -0,0 +1,6 @@
+I'm using git-annex to sync my photos across multiple computers, and it works beautifully. I would also like to sync Lightroom catalogues. The photo editing program creates a *.lrdata directory where it stores the edits in its own tree format. Merging two such directories obviously creates a mess. 
+
+Is there an elegant way to tell git-annex to treat the whole directory as a single file and overwrite the whole directory structure at once? I'm guessing the same problem occurs with mac os packages.
+
+Many thanks!
+Alex
diff --git a/doc/install/Docker.mdwn b/doc/install/Docker.mdwn
--- a/doc/install/Docker.mdwn
+++ b/doc/install/Docker.mdwn
@@ -30,3 +30,10 @@
 
 This will autobuild every hour at :15, and the autobuilt image will be
 left inside the container in /home/builder/gitbuilder/out/
+
+# container for backport building
+
+For building the Debian stable backport, the container
+`joeyh/git-annex-wheezy-backport` is used. This is nothing special, it
+just has the right versions of build dependencies installed from Debian
+stable and backports.
diff --git a/doc/publicrepos.mdwn b/doc/publicrepos.mdwn
--- a/doc/publicrepos.mdwn
+++ b/doc/publicrepos.mdwn
@@ -5,15 +5,22 @@
   `git clone https://downloads.kitenet.net/.git/`  
   Various downloads of things produced by Joey Hess, including git-annex
   builds and videos.
+
 * debconf-share  
   `git clone http://annex.debconf.org/debconf-share/.git/`  
   [DebConf](http://debconf.org/) Media, photos, videos, etc.
+
 * [conference-proceedings](https://github.com/RichiH/conference_proceedings)  
   `git clone https://github.com/RichiH/conference_proceedings.git`  
   A growing collection of videos of technology conferences.
   Submit a pull request to add your own!
+
 * [ocharles's papers](https://github.com/ocharles/papers)  
   Lots of CS papers read by [Oliver](http://ocharles.org.uk/blog/).
+
+* [MRI brain scan data](http://studyforrest.org/pages/access.html)  
+  `git clone http://psydata.ovgu.de/forrest_gump/.git studyforrest`  
+  High-resolution, ultra-highfield fMRI dataset on auditory perception.
 
 This is a wiki -- add your own public repository to the list!
 See [[tips/centralized_git_repository_tutorial]].
diff --git a/doc/related_software.mdwn b/doc/related_software.mdwn
--- a/doc/related_software.mdwn
+++ b/doc/related_software.mdwn
@@ -13,3 +13,5 @@
 * [git annex darktable integration](https://github.com/xxv/darktable-git-annex)
 * [Magit](http://github.com/magit/magit), an Emacs mode for Git, has
   [an extension](https://github.com/magit/magit-annex) for git annex.
+* [DataLad](http://datalad.org/) uses git-annex to provide access to
+  scientific data available from various sources.
diff --git a/doc/special_remotes/rsync.mdwn b/doc/special_remotes/rsync.mdwn
--- a/doc/special_remotes/rsync.mdwn
+++ b/doc/special_remotes/rsync.mdwn
@@ -2,12 +2,12 @@
 
 Setup example:
 
-	# git annex initremote myrsync type=rsync rsyncurl=rsync://rsync.example.com/myrsync keyid=joey@kitenet.net
+	# git annex initremote myrsync type=rsync rsyncurl=rsync://rsync.example.com/myrsync keyid=joey@kitenet.net encryption=shared
 	# git annex describe myrsync "rsync server"
 
 Or for using rsync over SSH
 
-	# git annex initremote myrsync type=rsync rsyncurl=ssh.example.com:/myrsync keyid=joey@kitenet.net
+	# git annex initremote myrsync type=rsync rsyncurl=ssh.example.com:/myrsync keyid=joey@kitenet.net encryption=shared
 	# git annex describe myrsync "rsync server"
 
 ## configuration
diff --git a/doc/thanks.mdwn b/doc/thanks.mdwn
--- a/doc/thanks.mdwn
+++ b/doc/thanks.mdwn
@@ -11,8 +11,8 @@
 <img alt="NSF logo" src="https://www.nsf.gov/images/logos/nsf1.gif">
 
 git-annex development is partially supported by the
-[NSF](https://www.nsf.gov/) as a part of the
-[DataGit project](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1429999).
+[NSF](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1429999) as a part of the
+[DataLad project](http://datalad.org/).
 
 ## 2013-2014
 
diff --git a/doc/tips/dumb_metadata_extraction_from_xbmc.mdwn b/doc/tips/dumb_metadata_extraction_from_xbmc.mdwn
--- a/doc/tips/dumb_metadata_extraction_from_xbmc.mdwn
+++ b/doc/tips/dumb_metadata_extraction_from_xbmc.mdwn
@@ -20,7 +20,7 @@
 
     git annex view playCount=0
 
-Use `git checkout master` to reset the view. Note that the above will flatten the tree hierarchy, which you may not way. Try this in that case:
+Use `git checkout master` to reset the view. Note that the above will flatten the tree hierarchy, which you may not want. Try this in that case:
 
     git annex view playCount=0 films/=*
 
diff --git a/doc/tips/dumb_metadata_extraction_from_xbmc/git-annex-xbmc-playcount.pl b/doc/tips/dumb_metadata_extraction_from_xbmc/git-annex-xbmc-playcount.pl
--- a/doc/tips/dumb_metadata_extraction_from_xbmc/git-annex-xbmc-playcount.pl
+++ b/doc/tips/dumb_metadata_extraction_from_xbmc/git-annex-xbmc-playcount.pl
@@ -1,28 +1,227 @@
 #! /usr/bin/perl -w
 
-my $dbpath="/home/video/.xbmc/userdata/Database/MyVideos75.db";
-my $prefix="/home/media/video/";
+use Getopt::Long;
+use Pod::Usage;
 
-my @lines = `echo 'SELECT playCount, path.strPath, files.strFileName FROM movie JOIN files ON files.idFile=movie.idFile JOIN path ON path.idPath=files.idPath;' | sqlite3 $dbpath`;
-for (@lines) {
-    my ($count, $dir, $file) = split /\|/;
-    chomp $file;
-    # empty or non-numeric count is zero
-    if ($count !~ /[0-9]/) {
-        $count = 0;
+my $help = 0;
+my $usage = 0;
+my $dryrun = 0;
+my $verbose = 0;
+my $path = '';
+my $annex = '';
+my $home = $ENV{'HOME'};
+
+sub main() {
+    checkargs();
+    if (!$path) {
+        $path = $home . '/.xbmc/userdata/Database';
     }
-    $dir =~ s/$prefix//;
-    if ($file =~ s#stack://##) {
-        for (split /,/, $file) {
-            s/$prefix//;
-            s/^ //;
-            s/ $//;
-            my @cmd = (qw(git annex metadata --set), "playCount=$count", $_);
-            system(@cmd);
-        }
+    print("# checking XBMC directory '$path'\n") if ($verbose);
+    $dbpath = finddb($path);
+    if (!$dbpath) {
+        pod2usage("$0: can't find a XBMC database in '$path'.");
     }
+    print("# using database '$dbpath'\n") if ($verbose);
+    checkdb();
+}
+
+# list videos database, find the latest one
+# modified version of
+# http://stackoverflow.com/questions/4651092/getting-the-list-of-files-sorted-by-modification-date-in-perl
+sub finddb($) {
+    my $path = shift(@_);
+    opendir my($dirh), $path or die "can't opendir $path: $!";
+    my @flist = sort {  -M $a <=> -M $b } # Sort by modification time
+        map  { "$path/$_" } # We need full paths for sorting
+        grep { /^MyVideos.*\.db$/ }
+        readdir $dirh;
+    closedir $dirh;
+    if ($#flist > 0) {
+        return $flist[0];
+    }
     else {
-        my @cmd = (qw(git annex metadata --set), "playCount=$count", "$dir$file");
-        system(@cmd);
+        return 0;
     }
 }
+
+sub checkargs() {
+    pod2usage(1) if $help;
+    pod2usage(-exitval => 0, -verbose => 2) if $usage;
+
+    GetOptions('h|?' => \$help,
+               'help|usage' => \$usage,
+               # we want to operate on relative links, so set this to
+               # the common annex to the git annex repo
+               'annex=s' => \$annex,
+               'path=s' => \$path,
+               'home=s' => \$home,
+               'dryrun|n' => \$dryrun,
+               'verbose|v' => \$verbose,
+        )
+        or die("Error parsing commandline\n");
+}
+
+sub checkdb() {
+    my @lines = `echo 'SELECT playCount, path.strPath, files.strFileName FROM movie JOIN files ON files.idFile=movie.idFile JOIN path ON path.idPath=files.idPath;' | sqlite3 $dbpath`;
+    print "# finding files...\n" if $verbose;
+    for (@lines) {
+        my ($count, $dir, $file) = split /\|/;
+        chomp $file;
+        # empty or non-numeric count is zero
+        if ($count !~ /[0-9]/) {
+            $count = 0;
+        }
+        print "# $dir/$file\n" if $verbose;
+        if ($file =~ s#stack://##) {
+            for (split /,/, $file) {
+                s/$annex//;
+                s/^ //;
+                s/ $//;
+                my @cmd = (qw(git annex metadata --set), "playCount=$count", $_);
+                if ($dryrun) {
+                    print join(' ', @cmd) . "\n";
+                }
+                else {
+                    system(@cmd);
+                }
+            }
+        }
+        else {
+            $dir =~ s/$annex//;
+            my @cmd = (qw(git annex metadata --set), "playCount=$count", "$dir$file");
+            if ($dryrun) {
+                print join(' ', @cmd) . "\n";
+            }
+            else {
+                system(@cmd);
+            }
+        }
+    }
+}
+
+main();
+
+__END__
+=encoding utf8
+
+=head1 NAME
+
+git-annex-xbmc-playcount - register XBMC playcounts as git-annex metadata
+
+=head1 SYNOPSIS
+
+git-annex-xbmc-playcount [--path .xbmc/userdata/Database]
+
+ Options:
+  -h         short usage
+  --help     complete help
+  --dryrun, -n do nothing and show the commands that would be ran
+  --annex    path to the git-annex repo
+  --home     the home directory where the .xbmc directory is located
+  --path     the location of the Database directory of XBMC, overrides --home
+  --verbose  show interaction details with the database
+
+=head1 DESCRIPTION
+
+This program will look into the XBMC database for the "playcount"
+field to register that number as metadata in the git-annex repository.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--dryrun>
+
+Do nothing but show all the steps that would be ran. The output can be
+piped through a POSIX shell after inspection. B<-n> is an alias of
+this command. Example:
+
+    git-annex-xbmc-playcount -n | tee runme
+    # inspect the output
+    sh < runme
+
+=item B<--annex>
+
+This option allows the user to specify the root of the git-annex
+repository, which is then stripped off the paths found in the XBMC
+database.
+
+=item B<--home>
+
+Home of the user running XBMC. If not specified, defaults to the $HOME
+environment variables. The script will look into
+B<$home/.xbmc/userdata/Database> for a file matching
+B<^MyVideos.*\.db$> and will fail if none is found.
+
+=item B<--path>
+
+Manually specify the path to B<.xbmc/userdata/Database>. This
+overrides B<--home>.
+
+Note that this doesn't point directly to the datbase itself, because
+there are usually many database files and we want to automatically
+find the latest. This may be a stupid limitation.
+
+=item B<--verbose>
+
+Show more information about path discovery. Doesn't obstruct
+B<--dryrun> output because lines are prefixed with C<#>.
+
+=back
+
+=head1 EXAMPLES
+
+You have a git annex in B</srv/video> and XBMC is ran as the
+B<video> user and you want to be cautious:
+
+    $ ./git-annex-xbmc-playcount.pl --home /home/video/ -n --annex /srv/video/ | tee set-metadata
+    git annex metadata --set playCount=0 films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
+
+This looks about right, set the metadata:
+
+    $ git annex metadata --set playCount=0 films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
+    metadata films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
+      lastchanged=2014-10-04@22-17-42
+      playCount=0
+      playCount-lastchanged=2014-10-04@22-17-42
+    ok
+    (Recording state in git...)
+
+=head1 ENVIRONMENT
+
+B<$HOME> is looked into to find the B<.xbmc> home directory if none of
+B<--home> or B<--path> is specified.
+
+=head1 FILES
+
+=over 8
+
+=item B<$HOME/.xbmc/userdata/Database/MyVideos.*\.db>
+
+This is where we assume the SQLite database of videos XBMC uses is
+stored.
+
+=back
+
+=head1 BUGS
+
+If there are pipes (C<|>) in filenames, the script may fail to find
+the files properly. We would need to rewrite the database code to use
+B<DBD::SQLite>(3pm) instead of a pipe to B<sqlite3>(1).
+
+=head1 LIMITATIONS
+
+It took longer writing this help than writing the stupid script.
+
+The script will not tag files not yet detected by XBMC.
+
+The script is not incremental, so it will repeatedly add the same
+counts to files it has already found.
+
+=head1 SEE ALSO
+
+B<git-annex>(1), B<xbmc>(1)
+
+=head1 AUTHOR
+
+Written by Antoine Beaupré <anarcat@debian.org>
diff --git a/doc/todo/read-only_removable_drives.mdwn b/doc/todo/read-only_removable_drives.mdwn
--- a/doc/todo/read-only_removable_drives.mdwn
+++ b/doc/todo/read-only_removable_drives.mdwn
@@ -5,3 +5,5 @@
 Otherwise, I would welcome advice on how to fix this problem without doing a `sudo chown -R` every time i plug this drive somewhere ... --[[anarcat]]
 
 > Workaround: `sudo setfacl -R -m u:anarcat:rwx /media/foo/annex`
+
+Note: this seems like there was at least one dupe opened about this in [[bugs/annex_get_fails_from_read-only_filesystem]].
diff --git a/doc/todo/vicfg_comment_gotcha.mdwn b/doc/todo/vicfg_comment_gotcha.mdwn
new file mode 100644
--- /dev/null
+++ b/doc/todo/vicfg_comment_gotcha.mdwn
@@ -0,0 +1,16 @@
+A user might run vicfg and want to reset a line back to the default value
+from the value they have periously set. A natural way to do that is to
+comment out the line (or delete it). However, what that actually does is
+vicfg parses the result and skips over that setting, since it's not
+present, and so no change is saved.
+
+It could try to parse commented out lines and detect deleted lines,
+but that way lies madness. Also, it's not at all clear what the "default"
+should be in response to such an action. The default varies per type of
+configuration, and vicfg does't know about defaults.
+
+Instead, I think it should detect when a setting provided in the input
+version of the file is not present in the output version, and plop the user
+back into the editor with an error, telling them that cannot be handled,
+and suggesting they instead change the value to the value they now want it
+to have.
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.20140927
+Version: 5.20141013
 Cabal-Version: >= 1.8
 License: GPL-3
 Maintainer: Joey Hess <joey@kitenet.net>
@@ -18,13 +18,18 @@
  dealing with files larger than git can currently easily handle, whether due
  to limitations in memory, time, or disk space.
  .
- Even without file content tracking, being able to manage files with git,
- move files around and delete files with versioned directory trees, and use
- branches and distributed clones, are all very handy reasons to use git. And
- annexed files can co-exist in the same git repository with regularly
- versioned files, which is convenient for maintaining documents, Makefiles,
- etc that are associated with annexed files but that benefit from full
- revision control.
+ It can store large files in many places, from local hard drives, to a
+ large number of cloud storage services, including S3, WebDAV,
+ and rsync, with a dozen cloud storage providers usable via plugins.
+ Files can be stored encrypted with gpg, so that the cloud storage
+ provider cannot see your data. git-annex keeps track of where each file
+ is stored, so it knows how many copies are available, and has many
+ facilities to ensure your data is preserved.
+ .
+ git-annex can also be used to keep a folder in sync between computers,
+ noticing when files are changed, and automatically committing them
+ to git and transferring them to other computers. The git-annex webapp
+ makes it easy to set up and use git-annex this way.
 
 Flag S3
   Description: Enable S3 support
