diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
+tags
+Build/SysConfig.hs
+Setup
+github-backup
+gitriddance
+
+dist
+cabal-dev
+*.o
+*.hi
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+*.prof
+*.aux
+*.hp
+.stack-work/
diff --git a/Build/Configure.hs b/Build/Configure.hs
--- a/Build/Configure.hs
+++ b/Build/Configure.hs
@@ -1,5 +1,7 @@
 {- Checks system configuration and generates SysConfig.hs. -}
 
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 module Build.Configure where
 
 import System.Environment
diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,16 @@
+github-backup (1.20160207) unstable; urgency=medium
+
+  * Switch to using https instead of git:// for a secure transport.
+    Note that existing git:// remotes will continue to be used.
+    Thanks, Robin Schneider.
+  * Add upper bound on github dependency, as version 0.14 has large API
+    changes and can't be used yet.
+  * Various updates to internal git and utility libraries shared
+    with git-annex.
+  * Silence build warnings with ghc 7.10.
+
+ -- Joey Hess <id@joeyh.name>  Sun, 07 Feb 2016 23:29:59 -0400
+
 github-backup (1.20150807) unstable; urgency=medium
 
   * Added bash completion.
diff --git a/Git/Construct.hs b/Git/Construct.hs
--- a/Git/Construct.hs
+++ b/Git/Construct.hs
@@ -58,24 +58,29 @@
  - specified. -}
 fromAbsPath :: FilePath -> IO Repo
 fromAbsPath dir
-	| absoluteGitPath dir = ifM (doesDirectoryExist dir') ( ret dir' , hunt )
+	| absoluteGitPath dir = hunt
 	| otherwise =
 		error $ "internal error, " ++ dir ++ " is not absolute"
   where
 	ret = pure . newFrom . LocalUnknown
-	{- Git always looks for "dir.git" in preference to
-	 - to "dir", even if dir ends in a "/". -}
 	canondir = dropTrailingPathSeparator dir
-	dir' = canondir ++ ".git"
 	{- When dir == "foo/.git", git looks for "foo/.git/.git",
 	 - and failing that, uses "foo" as the repository. -}
 	hunt
 		| (pathSeparator:".git") `isSuffixOf` canondir =
 			ifM (doesDirectoryExist $ dir </> ".git")
 				( ret dir
-				, ret $ takeDirectory canondir
+				, ret (takeDirectory canondir)
 				)
-		| otherwise = ret dir
+		| otherwise = ifM (doesDirectoryExist dir)
+			( ret dir
+			-- git falls back to dir.git when dir doesn't
+			-- exist, as long as dir didn't end with a
+			-- path separator
+			, if dir == canondir
+				then ret (dir ++ ".git")
+				else ret dir
+			)
 
 {- Remote Repo constructor. Throws exception on invalid url.
  -
diff --git a/Git/Queue.hs b/Git/Queue.hs
--- a/Git/Queue.hs
+++ b/Git/Queue.hs
@@ -15,6 +15,7 @@
 	size,
 	full,
 	flush,
+	merge,
 ) where
 
 import Utility.SafeCommand
@@ -25,14 +26,11 @@
 
 import qualified Data.Map as M
 
-{- Queable actions that can be performed in a git repository.
- -}
+{- Queable actions that can be performed in a git repository. -}
 data Action
 	{- Updating the index file, using a list of streamers that can
 	 - be added to as the queue grows. -}
-	= UpdateIndexAction
-		{ getStreamers :: [Git.UpdateIndex.Streamer] -- in reverse order
-		}
+	= UpdateIndexAction [Git.UpdateIndex.Streamer] -- in reverse order
 	{- A git command to run, on a list of files that can be added to
 	 - as the queue grows. -}
 	| CommandAction 
@@ -84,13 +82,11 @@
 addCommand subcommand params files q repo =
 	updateQueue action different (length files) q repo
   where
-	key = actionKey action
 	action = CommandAction
 		{ getSubcommand = subcommand
 		, getParams = params
-		, getFiles = allfiles
+		, getFiles = map File files
 		}
-	allfiles = map File files ++ maybe [] getFiles (M.lookup key $ items q)
 	
 	different (CommandAction { getSubcommand = s }) = s /= subcommand
 	different _ = True
@@ -100,10 +96,8 @@
 addUpdateIndex streamer q repo =
 	updateQueue action different 1 q repo
   where
-	key = actionKey action
 	-- the list is built in reverse order
-	action = UpdateIndexAction $ streamer : streamers
-	streamers = maybe [] getStreamers $ M.lookup key $ items q
+	action = UpdateIndexAction [streamer]
 
 	different (UpdateIndexAction _) = False
 	different _ = True
@@ -123,7 +117,23 @@
 			, items = newitems
 			}
 		!newsize = size q' + sizeincrease
-		!newitems = M.insertWith' const (actionKey action) action (items q')
+		!newitems = M.insertWith' combineNewOld (actionKey action) action (items q')
+
+combineNewOld :: Action -> Action -> Action
+combineNewOld (CommandAction _sc1 _ps1 fs1) (CommandAction sc2 ps2 fs2) =
+	CommandAction sc2 ps2 (fs1++fs2)
+combineNewOld (UpdateIndexAction s1) (UpdateIndexAction s2) =
+	UpdateIndexAction (s1++s2)
+combineNewOld anew _aold = anew
+
+{- Merges the contents of the second queue into the first.
+ - This should only be used when the two queues are known to contain
+ - non-conflicting actions. -}
+merge :: Queue -> Queue -> Queue
+merge origq newq = origq
+	{ size = size origq + size newq
+	, items = M.unionWith combineNewOld (items newq) (items origq)
+	}
 
 {- Is a queue large enough that it should be flushed? -}
 full :: Queue -> Bool
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,5 +1,7 @@
 {- cabal setup file -}
 
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 import Distribution.Simple
 import Distribution.Simple.Setup
 
diff --git a/Utility/Exception.hs b/Utility/Exception.hs
--- a/Utility/Exception.hs
+++ b/Utility/Exception.hs
@@ -20,7 +20,8 @@
 	catchNonAsync,
 	tryNonAsync,
 	tryWhenExists,
-	catchHardwareFault,
+	catchIOErrorType,
+	IOErrorType(..)
 ) where
 
 import Control.Monad.Catch as X hiding (Handler)
@@ -39,10 +40,7 @@
 
 {- Catches IO errors and returns a Maybe -}
 catchMaybeIO :: MonadCatch m => m a -> m (Maybe a)
-catchMaybeIO a = do
-	catchDefaultIO Nothing $ do
-		v <- a
-		return (Just v)
+catchMaybeIO a = catchDefaultIO Nothing $ a >>= (return . Just)
 
 {- Catches IO errors and returns a default value. -}
 catchDefaultIO :: MonadCatch m => a -> m a -> m a
@@ -91,11 +89,11 @@
 	v <- tryJust (guard . isDoesNotExistError) a
 	return (eitherToMaybe v)
 
-{- Catches only exceptions caused by hardware faults.
- - Ie, disk IO error. -}
-catchHardwareFault :: MonadCatch m => m a -> (IOException -> m a) -> m a
-catchHardwareFault a onhardwareerr = catchIO a onlyhw
+{- Catches only IO exceptions of a particular type.
+ - Ie, use HardwareFault to catch disk IO errors. -}
+catchIOErrorType :: MonadCatch m => IOErrorType -> (IOException -> m a) -> m a -> m a
+catchIOErrorType errtype onmatchingerr a = catchIO a onlymatching
   where
-	onlyhw e
-		| ioeGetErrorType e == HardwareFault = onhardwareerr e
+	onlymatching e
+		| ioeGetErrorType e == errtype = onmatchingerr e
 		| otherwise = throwM e
diff --git a/Utility/FileMode.hs b/Utility/FileMode.hs
--- a/Utility/FileMode.hs
+++ b/Utility/FileMode.hs
@@ -7,7 +7,10 @@
 
 {-# LANGUAGE CPP #-}
 
-module Utility.FileMode where
+module Utility.FileMode (
+	module Utility.FileMode,
+	FileMode,
+) where
 
 import System.IO
 import Control.Monad
@@ -17,18 +20,32 @@
 import System.Posix.Files
 #endif
 import Foreign (complement)
+import Control.Monad.IO.Class (liftIO, MonadIO)
+import Control.Monad.Catch
 
 import Utility.Exception
 
 {- Applies a conversion function to a file's mode. -}
 modifyFileMode :: FilePath -> (FileMode -> FileMode) -> IO ()
-modifyFileMode f convert = do
+modifyFileMode f convert = void $ modifyFileMode' f convert
+
+modifyFileMode' :: FilePath -> (FileMode -> FileMode) -> IO FileMode
+modifyFileMode' f convert = do
 	s <- getFileStatus f
 	let old = fileMode s
 	let new = convert old
 	when (new /= old) $
 		setFileMode f new
+	return old
 
+{- Runs an action after changing a file's mode, then restores the old mode. -}
+withModifiedFileMode :: FilePath -> (FileMode -> FileMode) -> IO a -> IO a
+withModifiedFileMode file convert a = bracket setup cleanup go
+  where
+	setup = modifyFileMode' file convert
+	cleanup oldmode = modifyFileMode file (const oldmode)
+	go _ = a
+
 {- Adds the specified FileModes to the input mode, leaving the rest
  - unchanged. -}
 addModes :: [FileMode] -> FileMode -> FileMode
@@ -92,7 +109,7 @@
 
 {- Runs an action without that pesky umask influencing it, unless the
  - passed FileMode is the standard one. -}
-noUmask :: FileMode -> IO a -> IO a
+noUmask :: (MonadIO m, MonadMask m) => FileMode -> m a -> m a
 #ifndef mingw32_HOST_OS
 noUmask mode a
 	| mode == stdFileMode = a
@@ -101,12 +118,12 @@
 noUmask _ a = a
 #endif
 
-withUmask :: FileMode -> IO a -> IO a
+withUmask :: (MonadIO m, MonadMask m) => FileMode -> m a -> m a
 #ifndef mingw32_HOST_OS
 withUmask umask a = bracket setup cleanup go
   where
-	setup = setFileCreationMask umask
-	cleanup = setFileCreationMask
+	setup = liftIO $ setFileCreationMask umask
+	cleanup = liftIO . setFileCreationMask
 	go _ = a
 #else
 withUmask _ a = a
diff --git a/Utility/FileSystemEncoding.hs b/Utility/FileSystemEncoding.hs
--- a/Utility/FileSystemEncoding.hs
+++ b/Utility/FileSystemEncoding.hs
@@ -13,6 +13,7 @@
 	withFilePath,
 	md5FilePath,
 	decodeBS,
+	encodeBS,
 	decodeW8,
 	encodeW8,
 	encodeW8NUL,
@@ -28,12 +29,15 @@
 import qualified Data.Hash.MD5 as MD5
 import Data.Word
 import Data.Bits.Utils
+import Data.List
 import Data.List.Utils
 import qualified Data.ByteString.Lazy as L
 #ifdef mingw32_HOST_OS
 import qualified Data.ByteString.Lazy.UTF8 as L8
 #endif
 
+import Utility.Exception
+
 {- Sets a Handle to use the filesystem encoding. This causes data
  - written or read from it to be encoded/decoded the same
  - as ghc 7.4 does to filenames etc. This special encoding
@@ -67,12 +71,16 @@
  - only allows doing this conversion with CStrings, and the CString buffer
  - is allocated, used, and deallocated within the call, with no side
  - effects.
+ -
+ - If the FilePath contains a value that is not legal in the filesystem
+ - encoding, rather than thowing an exception, it will be returned as-is.
  -}
 {-# NOINLINE _encodeFilePath #-}
 _encodeFilePath :: FilePath -> String
 _encodeFilePath fp = unsafePerformIO $ do
 	enc <- Encoding.getFileSystemEncoding
-	GHC.withCString enc fp $ GHC.peekCString Encoding.char8
+	GHC.withCString enc fp (GHC.peekCString Encoding.char8)
+		`catchNonAsync` (\_ -> return fp)
 
 {- Encodes a FilePath into a Md5.Str, applying the filesystem encoding. -}
 md5FilePath :: FilePath -> MD5.Str
@@ -81,13 +89,21 @@
 {- Decodes a ByteString into a FilePath, applying the filesystem encoding. -}
 decodeBS :: L.ByteString -> FilePath
 #ifndef mingw32_HOST_OS
-decodeBS = encodeW8 . L.unpack
+decodeBS = encodeW8NUL . L.unpack
 #else
 {- On Windows, we assume that the ByteString is utf-8, since Windows
  - only uses unicode for filenames. -}
 decodeBS = L8.toString
 #endif
 
+{- Encodes a FilePath into a ByteString, applying the filesystem encoding. -}
+encodeBS :: FilePath -> L.ByteString
+#ifndef mingw32_HOST_OS
+encodeBS = L.pack . decodeW8NUL
+#else
+encodeBS = L8.fromString
+#endif
+
 {- Converts a [Word8] to a FilePath, encoding using the filesystem encoding.
  -
  - w82c produces a String, which may contain Chars that are invalid
@@ -110,12 +126,12 @@
 
 {- Like encodeW8 and decodeW8, but NULs are passed through unchanged. -}
 encodeW8NUL :: [Word8] -> FilePath
-encodeW8NUL = join nul . map encodeW8 . split (s2w8 nul)
+encodeW8NUL = intercalate nul . map encodeW8 . split (s2w8 nul)
   where
 	nul = ['\NUL']
 
 decodeW8NUL :: FilePath -> [Word8]
-decodeW8NUL = join (s2w8 nul) . map decodeW8 . split nul
+decodeW8NUL = intercalate (s2w8 nul) . map decodeW8 . split nul
   where
 	nul = ['\NUL']
 
diff --git a/Utility/Misc.hs b/Utility/Misc.hs
--- a/Utility/Misc.hs
+++ b/Utility/Misc.hs
@@ -136,7 +136,7 @@
  - if this reap gets there first. -}
 reapZombies :: IO ()
 #ifndef mingw32_HOST_OS
-reapZombies = do
+reapZombies =
 	-- throws an exception when there are no child processes
 	catchDefaultIO Nothing (getAnyProcessStatus False True)
 		>>= maybe (return ()) (const reapZombies)
diff --git a/Utility/Path.hs b/Utility/Path.hs
--- a/Utility/Path.hs
+++ b/Utility/Path.hs
@@ -89,7 +89,7 @@
 upFrom :: FilePath -> Maybe FilePath
 upFrom dir
 	| length dirs < 2 = Nothing
-	| otherwise = Just $ joinDrive drive (join s $ init dirs)
+	| otherwise = Just $ joinDrive drive (intercalate s $ init dirs)
   where
 	-- on Unix, the drive will be "/" when the dir is absolute, otherwise ""
 	(drive, path) = splitDrive dir
@@ -149,7 +149,7 @@
 relPathDirToFileAbs :: FilePath -> FilePath -> FilePath
 relPathDirToFileAbs from to
 	| takeDrive from /= takeDrive to = to
-	| otherwise = join s $ dotdots ++ uncommon
+	| otherwise = intercalate s $ dotdots ++ uncommon
   where
 	s = [pathSeparator]
 	pfrom = split s from
@@ -288,7 +288,6 @@
 	if l <= 0
 		then return 255
 		else return $ minimum [l, 255]
-  where
 #endif
 
 {- Given a string that we'd like to use as the basis for FilePath, but that
diff --git a/Utility/Process.hs b/Utility/Process.hs
--- a/Utility/Process.hs
+++ b/Utility/Process.hs
@@ -31,6 +31,7 @@
 	withQuietOutput,
 	feedWithQuietOutput,
 	createProcess,
+	waitForProcess,
 	startInteractiveProcess,
 	stdinHandle,
 	stdoutHandle,
@@ -40,9 +41,12 @@
 	devNull,
 ) where
 
-import qualified System.Process
-import qualified System.Process as X hiding (CreateProcess(..), createProcess, runInteractiveProcess, readProcess, readProcessWithExitCode, system, rawSystem, runInteractiveCommand, runProcess)
-import System.Process hiding (createProcess, readProcess)
+import qualified Utility.Process.Shim
+import qualified Utility.Process.Shim as X hiding (CreateProcess(..), createProcess, runInteractiveProcess, readProcess, readProcessWithExitCode, system, rawSystem, runInteractiveCommand, runProcess)
+import Utility.Process.Shim hiding (createProcess, readProcess, waitForProcess)
+import Utility.Misc
+import Utility.Exception
+
 import System.Exit
 import System.IO
 import System.Log.Logger
@@ -57,9 +61,6 @@
 import Data.Maybe
 import Prelude
 
-import Utility.Misc
-import Utility.Exception
-
 type CreateProcessRunner = forall a. CreateProcess -> ((Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> IO a) -> IO a
 
 data StdHandle = StdinHandle | StdoutHandle | StderrHandle
@@ -171,22 +172,21 @@
 -- returns a transcript combining its stdout and stderr, and
 -- whether it succeeded or failed.
 processTranscript :: String -> [String] -> (Maybe String) -> IO (String, Bool)
-processTranscript cmd opts input = processTranscript' cmd opts Nothing input
+processTranscript = processTranscript' id
 
-processTranscript' :: String -> [String] -> Maybe [(String, String)] -> (Maybe String) -> IO (String, Bool)
-processTranscript' cmd opts environ input = do
+processTranscript' :: (CreateProcess -> CreateProcess) -> String -> [String] -> Maybe String -> IO (String, Bool)
+processTranscript' modproc cmd opts input = do
 #ifndef mingw32_HOST_OS
 {- This implementation interleves stdout and stderr in exactly the order
  - the process writes them. -}
 	(readf, writef) <- System.Posix.IO.createPipe
 	readh <- System.Posix.IO.fdToHandle readf
 	writeh <- System.Posix.IO.fdToHandle writef
-	p@(_, _, _, pid) <- createProcess $
+	p@(_, _, _, pid) <- createProcess $ modproc $
 		(proc cmd opts)
 			{ std_in = if isJust input then CreatePipe else Inherit
 			, std_out = UseHandle writeh
 			, std_err = UseHandle writeh
-			, env = environ
 			}
 	hClose writeh
 
@@ -198,12 +198,11 @@
 	return (transcript, ok)
 #else
 {- This implementation for Windows puts stderr after stdout. -}
-	p@(_, _, _, pid) <- createProcess $
+	p@(_, _, _, pid) <- createProcess $ modproc $
 		(proc cmd opts)
 			{ std_in = if isJust input then CreatePipe else Inherit
 			, std_out = CreatePipe
 			, std_err = CreatePipe
-			, env = environ
 			}
 
 	getout <- mkreader (stdoutHandle p)
@@ -345,22 +344,6 @@
 processHandle :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> ProcessHandle
 processHandle (_, _, _, pid) = pid
 
--- | Debugging trace for a CreateProcess.
-debugProcess :: CreateProcess -> IO ()
-debugProcess p = do
-	debugM "Utility.Process" $ unwords
-		[ action ++ ":"
-		, showCmd p
-		]
-  where
-	action
-		| piped (std_in p) && piped (std_out p) = "chat"
-		| piped (std_in p)                      = "feed"
-		| piped (std_out p)                     = "read"
-		| otherwise                             = "call"
-	piped Inherit = False
-	piped _ = True
-
 -- | Shows the command that a CreateProcess will run.
 showCmd :: CreateProcess -> String
 showCmd = go . cmdspec
@@ -385,9 +368,30 @@
 	(Just from, Just to, _, pid) <- createProcess p
 	return (pid, to, from)
 
--- | Wrapper around 'System.Process.createProcess' from System.Process,
--- that does debug logging.
+-- | Wrapper around 'System.Process.createProcess' that does debug logging.
 createProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
 createProcess p = do
 	debugProcess p
-	System.Process.createProcess p
+	Utility.Process.Shim.createProcess p
+
+-- | Debugging trace for a CreateProcess.
+debugProcess :: CreateProcess -> IO ()
+debugProcess p = debugM "Utility.Process" $ unwords
+	[ action ++ ":"
+	, showCmd p
+	]
+  where
+	action
+		| piped (std_in p) && piped (std_out p) = "chat"
+		| piped (std_in p)                      = "feed"
+		| piped (std_out p)                     = "read"
+		| otherwise                             = "call"
+	piped Inherit = False
+	piped _ = True
+
+-- | Wrapper around 'System.Process.waitForProcess' that does debug logging.
+waitForProcess ::  ProcessHandle -> IO ExitCode
+waitForProcess h = do
+	r <- Utility.Process.Shim.waitForProcess h
+	debugM "Utility.Process" ("process done " ++ show r)
+	return r
diff --git a/Utility/Process/Shim.hs b/Utility/Process/Shim.hs
new file mode 100644
--- /dev/null
+++ b/Utility/Process/Shim.hs
@@ -0,0 +1,3 @@
+module Utility.Process.Shim (module X) where
+
+import System.Process as X
diff --git a/Utility/SafeCommand.hs b/Utility/SafeCommand.hs
--- a/Utility/SafeCommand.hs
+++ b/Utility/SafeCommand.hs
@@ -14,6 +14,7 @@
 import Data.String.Utils
 import System.FilePath
 import Data.Char
+import Data.List
 import Control.Applicative
 import Prelude
 
@@ -85,7 +86,7 @@
 shellEscape f = "'" ++ escaped ++ "'"
   where
 	-- replace ' with '"'"'
-	escaped = join "'\"'\"'" $ split "'" f
+	escaped = intercalate "'\"'\"'" $ split "'" f
 
 -- | Unescapes a set of shellEscaped words or filenames.
 shellUnEscape :: String -> [String]
@@ -105,10 +106,10 @@
 		| otherwise = inquote q (w++[c]) cs
 
 -- | For quickcheck.
-prop_idempotent_shellEscape :: String -> Bool
-prop_idempotent_shellEscape s = [s] == (shellUnEscape . shellEscape) s
-prop_idempotent_shellEscape_multiword :: [String] -> Bool
-prop_idempotent_shellEscape_multiword s = s == (shellUnEscape . unwords . map shellEscape) s
+prop_isomorphic_shellEscape :: String -> Bool
+prop_isomorphic_shellEscape s = [s] == (shellUnEscape . shellEscape) s
+prop_isomorphic_shellEscape_multiword :: [String] -> Bool
+prop_isomorphic_shellEscape_multiword s = s == (shellUnEscape . unwords . map shellEscape) s
 
 -- | Segments a list of filenames into groups that are all below the maximum
 --  command-line length limit.
diff --git a/Utility/Tmp.hs b/Utility/Tmp.hs
--- a/Utility/Tmp.hs
+++ b/Utility/Tmp.hs
@@ -15,6 +15,9 @@
 import Control.Monad.IfElse
 import System.FilePath
 import Control.Monad.IO.Class
+#ifndef mingw32_HOST_OS
+import System.Posix.Temp (mkdtemp)
+#endif
 
 import Utility.Exception
 import Utility.FileSystemEncoding
@@ -64,32 +67,45 @@
  - directory and all its contents. -}
 withTmpDir :: (MonadMask m, MonadIO m) => Template -> (FilePath -> m a) -> m a
 withTmpDir template a = do
-	tmpdir <- liftIO $ catchDefaultIO "." getTemporaryDirectory
-	withTmpDirIn tmpdir template a
+	topleveltmpdir <- liftIO $ catchDefaultIO "." getTemporaryDirectory
+#ifndef mingw32_HOST_OS
+	-- Use mkdtemp to create a temp directory securely in /tmp.
+	bracket
+		(liftIO $ mkdtemp $ topleveltmpdir </> template)
+		removeTmpDir
+		a
+#else
+	withTmpDirIn topleveltmpdir template a
+#endif
 
 {- Runs an action with a tmp directory located within a specified directory,
  - then removes the tmp directory and all its contents. -}
 withTmpDirIn :: (MonadMask m, MonadIO m) => FilePath -> Template -> (FilePath -> m a) -> m a
-withTmpDirIn tmpdir template = bracketIO create remove
+withTmpDirIn tmpdir template = bracketIO create removeTmpDir
   where
-	remove d = whenM (doesDirectoryExist d) $ do
-#if mingw32_HOST_OS
-		-- Windows will often refuse to delete a file
-		-- after a process has just written to it and exited.
-		-- Because it's crap, presumably. So, ignore failure
-		-- to delete the temp directory.
-		_ <- tryIO $ removeDirectoryRecursive d
-		return ()
-#else
-		removeDirectoryRecursive d
-#endif
 	create = do
 		createDirectoryIfMissing True tmpdir
 		makenewdir (tmpdir </> template) (0 :: Int)
 	makenewdir t n = do
 		let dir = t ++ "." ++ show n
-		either (const $ makenewdir t $ n + 1) (const $ return dir)
-			=<< tryIO (createDirectory dir)
+		catchIOErrorType AlreadyExists (const $ makenewdir t $ n + 1) $ do
+			createDirectory dir
+			return dir
+
+{- Deletes the entire contents of the the temporary directory, if it
+ - exists. -}
+removeTmpDir :: MonadIO m => FilePath -> m ()
+removeTmpDir tmpdir = liftIO $ whenM (doesDirectoryExist tmpdir) $ do
+#if mingw32_HOST_OS
+	-- Windows will often refuse to delete a file
+	-- after a process has just written to it and exited.
+	-- Because it's crap, presumably. So, ignore failure
+	-- to delete the temp directory.
+	_ <- tryIO $ removeDirectoryRecursive tmpdir
+	return ()
+#else
+	removeDirectoryRecursive tmpdir
+#endif
 
 {- It's not safe to use a FilePath of an existing file as the template
  - for openTempFile, because if the FilePath is really long, the tmpfile
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+github-backup (1.20160207) unstable; urgency=medium
+
+  * Switch to using https instead of git:// for a secure transport.
+    Note that existing git:// remotes will continue to be used.
+    Thanks, Robin Schneider.
+  * Add upper bound on github dependency, as version 0.14 has large API
+    changes and can't be used yet.
+  * Various updates to internal git and utility libraries shared
+    with git-annex.
+  * Silence build warnings with ghc 7.10.
+
+ -- Joey Hess <id@joeyh.name>  Sun, 07 Feb 2016 23:29:59 -0400
+
 github-backup (1.20150807) unstable; urgency=medium
 
   * Added bash completion.
diff --git a/debian/files b/debian/files
deleted file mode 100644
--- a/debian/files
+++ /dev/null
@@ -1,1 +0,0 @@
-github-backup_1.20150619_amd64.deb utils optional
diff --git a/debian/github-backup.debhelper.log b/debian/github-backup.debhelper.log
deleted file mode 100644
--- a/debian/github-backup.debhelper.log
+++ /dev/null
@@ -1,20 +0,0 @@
-dh_auto_configure
-dh_auto_build
-dh_auto_test
-dh_prep
-dh_auto_install
-dh_installdocs
-dh_installchangelogs
-dh_installman
-dh_perl
-dh_link
-dh_compress
-dh_fixperms
-dh_strip
-dh_makeshlibs
-dh_shlibdeps
-dh_installdeb
-dh_gencontrol
-dh_md5sums
-dh_builddeb
-dh_builddeb
diff --git a/debian/github-backup.substvars b/debian/github-backup.substvars
deleted file mode 100644
--- a/debian/github-backup.substvars
+++ /dev/null
@@ -1,3 +0,0 @@
-shlibs:Depends=libc6 (>= 2.14), libffi6 (>= 3.0.4), libgmp10, zlib1g (>= 1:1.1.4)
-misc:Depends=
-misc:Pre-Depends=
diff --git a/github-backup.cabal b/github-backup.cabal
--- a/github-backup.cabal
+++ b/github-backup.cabal
@@ -1,5 +1,5 @@
 Name: github-backup
-Version: 1.20150807
+Version: 1.20160207
 Cabal-Version: >= 1.8
 Maintainer: Joey Hess <joey@kitenet.net>
 Author: Joey Hess
@@ -30,7 +30,7 @@
   Build-Depends: MissingH, hslogger, directory, filepath, containers, mtl,
    network, exceptions, transformers, unix-compat, bytestring,
    IfElse, pretty-show, text, process, optparse-applicative,
-   github >= 0.7.2,
+   github >= 0.7.2 && < 0.14.0,
    base >= 4.5, base < 5
   
   if (! os(windows))
@@ -45,8 +45,8 @@
 
 Executable gitriddance
   Main-Is: gitriddance.hs
-  GHC-Options: -Wall
-  Build-Depends: github >= 0.13.1, base >= 4.5, base < 5, text, filepath,
+  GHC-Options: -Wall -fno-warn-tabs
+  Build-Depends: github >= 0.13.1 && < 0.14.0, base >= 4.5, base < 5, text, filepath,
     MissingH, exceptions, transformers, bytestring, hslogger, process,
     containers, unix-compat, IfElse, directory, mtl
   
diff --git a/github-backup.hs b/github-backup.hs
--- a/github-backup.hs
+++ b/github-backup.hs
@@ -50,11 +50,11 @@
 
 repoUrl :: GithubUserRepo -> String
 repoUrl (GithubUserRepo user remote) =
-	"git://github.com/" ++ user ++ "/" ++ remote ++ ".git"
+	"https://github.com/" ++ user ++ "/" ++ remote ++ ".git"
 
 repoWikiUrl :: GithubUserRepo -> String
 repoWikiUrl (GithubUserRepo user remote) =
-	"git://github.com/" ++ user ++ "/" ++ remote ++ ".wiki.git"
+	"https://github.com/" ++ user ++ "/" ++ remote ++ ".wiki.git"
 
 -- A name for a github api call.
 type ApiName = String
