github-backup 1.20150106 → 1.20150617
raw patch · 45 files changed
+612/−211 lines, 45 filesdep +Win32dep +setenvdep +utf8-string
Dependencies added: Win32, setenv, utf8-string
Files
- Build/TestConfig.hs +2/−0
- Build/Version.hs +9/−7
- CHANGELOG +189/−0
- COPYRIGHT +35/−0
- Git.hs +32/−4
- Git/Branch.hs +2/−5
- Git/BuildVersion.hs +1/−1
- Git/CatFile.hs +2/−2
- Git/Command.hs +2/−2
- Git/Config.hs +19/−5
- Git/Construct.hs +10/−11
- Git/DiffTreeItem.hs +1/−1
- Git/FilePath.hs +2/−3
- Git/HashObject.hs +2/−2
- Git/Queue.hs +1/−1
- Git/Ref.hs +4/−1
- Git/Remote.hs +1/−1
- Git/Sha.hs +1/−1
- Git/Types.hs +1/−1
- Git/UpdateIndex.hs +1/−1
- Git/Url.hs +1/−1
- Git/Version.hs +3/−1
- Utility/Applicative.hs +1/−1
- Utility/CoProcess.hs +1/−1
- Utility/Data.hs +3/−1
- Utility/Directory.hs +4/−2
- Utility/DottedVersion.hs +3/−1
- Utility/Env.hs +3/−1
- Utility/Exception.hs +15/−2
- Utility/FileMode.hs +9/−16
- Utility/FileSystemEncoding.hs +19/−1
- Utility/Misc.hs +7/−5
- Utility/Monad.hs +3/−1
- Utility/PartialPrelude.hs +2/−0
- Utility/Path.hs +51/−24
- Utility/PosixFiles.hs +2/−1
- Utility/Process.hs +80/−44
- Utility/SafeCommand.hs +61/−45
- Utility/Tmp.hs +2/−1
- Utility/URI.hs +1/−1
- Utility/UserInfo.hs +5/−3
- debian/changelog +9/−0
- debian/rules +0/−4
- github-backup.cabal +9/−4
- github-backup.hs +1/−1
Build/TestConfig.hs view
@@ -1,5 +1,7 @@ {- Tests the system and generates Build.SysConfig.hs. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Build.TestConfig where import Utility.Path
Build/Version.hs view
@@ -1,5 +1,7 @@ {- Package version determination, for configure script. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Build.Version where import Data.Maybe@@ -10,14 +12,15 @@ import Data.Char import System.Process -import Build.TestConfig import Utility.Monad import Utility.Exception +type Version = String+ {- Set when making an official release. (Distribution vendors should set - this too.) -} isReleaseBuild :: IO Bool-isReleaseBuild = isJust <$> catchMaybeIO (getEnv "RELEASE_BUILD")+isReleaseBuild = (== Just "1") <$> catchMaybeIO (getEnv "RELEASE_BUILD") {- Version is usually based on the major version from the changelog, - plus the date of the last commit, plus the git rev of that commit.@@ -25,14 +28,14 @@ - - If git or a git repo is not available, or something goes wrong, - or this is a release build, just use the version from the changelog. -}-getVersion :: Test+getVersion :: IO Version getVersion = do changelogversion <- getChangelogVersion- version <- ifM (isReleaseBuild)+ ifM (isReleaseBuild) ( return changelogversion , catchDefaultIO changelogversion $ do let major = takeWhile (/= '.') changelogversion- autoversion <- readProcess "sh"+ autoversion <- takeWhile (\c -> isAlphaNum c || c == '-') <$> readProcess "sh" [ "-c" , "git log -n 1 --format=format:'%ci %h'| sed -e 's/-//g' -e 's/ .* /-g/'" ] ""@@ -40,9 +43,8 @@ then return changelogversion else return $ concat [ major, ".", autoversion ] )- return $ Config "packageversion" (StringConfig version) -getChangelogVersion :: IO String+getChangelogVersion :: IO Version getChangelogVersion = do changelog <- readFile "debian/changelog" let verline = takeWhile (/= '\n') changelog
+ CHANGELOG view
@@ -0,0 +1,189 @@+github-backup (1.20150617) unstable; urgency=medium++ * Add missing build deps for windows to cabal file.+ Thanks, Jeff Segal.+ * Various updates to internal git and utility libraries shared+ with git-annex.++ -- Joey Hess <id@joeyh.name> Wed, 17 Jun 2015 14:44:14 -0400++github-backup (1.20150106) unstable; urgency=medium++ * Fix build with process 1.2.1.0.+ * Various updates to internal git and utility libraries shared+ with git-annex.++ -- Joey Hess <id@joeyh.name> Tue, 06 Jan 2015 19:08:08 -0400++github-backup (1.20141222) unstable; urgency=medium++ * Added gitriddance(1), a utility to close all issues and pull requests,+ for repos that don't want to be bothered with GitHub's proprietary+ issue tracker.+ * gitriddance depends on github 0.13.1, which has bug fixes+ for posting comments.+ * Various updates to internal git and utility libraries shared+ with git-annex.++ -- Joey Hess <id@joeyh.name> Mon, 22 Dec 2014 15:30:08 -0400++github-backup (1.20141204) unstable; urgency=high++ * Fix broken argument parser for the username|organization parameter.+ Closes: #772043++ -- Joey Hess <id@joeyh.name> Thu, 04 Dec 2014 12:29:06 -0400++github-backup (1.20141110) unstable; urgency=medium++ * Orphaned the Debian package.+ (I continue to maintain github-backup upstream.)++ -- Joey Hess <joeyh@debian.org> Mon, 10 Nov 2014 12:19:59 -0400++github-backup (1.20141031) unstable; urgency=medium++ * Adjust cabal file for network-uri split.+ * Avoid using optparse-applicate's argument combinator, so it will build+ with 0.11 and older too.+ * Various updates to internal git and utility libraries shared with+ git-annex.++ -- Joey Hess <joeyh@debian.org> Fri, 31 Oct 2014 11:17:49 -0400++github-backup (1.20140831) unstable; urgency=medium++ * Fix build with github 0.10.++ -- Joey Hess <joeyh@debian.org> Sun, 31 Aug 2014 15:31:26 -0700++github-backup (1.20140807) unstable; urgency=medium++ * Fix build with github 0.9.+ * Fix creation of github branch.++ -- Joey Hess <joeyh@debian.org> Thu, 07 Aug 2014 22:17:22 -0400++github-backup (1.20140721) unstable; urgency=medium++ * Fix typo in fix for url parsing. Closes: #755261++ -- Joey Hess <joeyh@debian.org> Mon, 21 Jul 2014 13:10:49 -0400++github-backup (1.20140720) unstable; urgency=medium++ * Deal with trailing slashes on github repo urls. Closes: #755261+ * Fix bug introduced by change to embedded git libraries+ in last release. Closes: #755262++ -- Joey Hess <joeyh@debian.org> Sun, 20 Jul 2014 17:20:26 -0400++github-backup (1.20140707) unstable; urgency=medium++ * Add --exclude to skip backing up a specific repository+ when backing up a user or organization's repositories.+ Closes: #754072+ * Converted to using optparse-applicative.+ * Multiple usernames can now be specified to back up at once.++ -- Joey Hess <joeyh@debian.org> Mon, 07 Jul 2014 23:01:03 -0400++github-backup (1.20140704) unstable; urgency=medium++ * Avoid making signed commits when committing to the github-backup branch+ and the user has commit.gpgsign=true.+ Closes: #753720+ * Various updates to internal git and utility libraries shared with git-annex.++ -- Joey Hess <joeyh@debian.org> Fri, 04 Jul 2014 12:01:11 -0400++github-backup (1.20131203) unstable; urgency=low++ * Now also backs up the repos a user has starred, when run with a user's+ name.+ * Now finds and backs up the parent repository that a repository got forked+ from.+ * Uses authentication for all API calls.+ * Fairer ordering of requests when backing up many repositories at once.+ * Avoid making requests for data that has already been backed up until+ after new data has been backed up. Handles API rate limiting much better.+ Closes: #723859++ -- Joey Hess <joeyh@debian.org> Tue, 03 Dec 2013 12:45:18 -0400++github-backup (1.20131101) unstable; urgency=low++ * Now also backs up the repos a user is watching, when run with a user's+ name. Useful if you want to back up repositories that you have not forked;+ just watch them and run github-backup.+ * Can now log in to github, to avoid increasingly small API rate limits.+ Set GITHUB_USER and GITHUB_PASSWORD environment to enable.+ Note that a few api calls don't use authentication; see+ https://github.com/fpco/github/issues/40+ * Build-Depend on git. Closes: #728481+ * Don't include tmp directory in files stored in the github branch.++ -- Joey Hess <joeyh@debian.org> Fri, 01 Nov 2013 18:00:16 -0400++github-backup (1.20131006) unstable; urgency=low++ * Ported to Windows.+ * Improve error message when it fails to query github for repositories+ belonging to a user. Closes: #705084+ * Various updates to internal git and utility libraries shared with git-annex.+ * Makefile now uses cabal to build.++ -- Joey Hess <joeyh@debian.org> Sun, 06 Oct 2013 18:04:56 -0400++github-backup (1.20130622) unstable; urgency=low++ * Add missing unix-compat build dependency. Closes: #713279++ -- Joey Hess <joeyh@debian.org> Sat, 22 Jun 2013 13:08:57 -0400++github-backup (1.20130618) unstable; urgency=low++ * Much better creation and committing to the github branch. ++ -- Joey Hess <joeyh@debian.org> Mon, 17 Jun 2013 17:40:02 -0400++github-backup (1.20130617) unstable; urgency=low++ * Build-Depend on libghc-extensible-exceptions-dev. Closes: #712549+ * Various updates to internal git and utility libraries shared with+ git-annex, including some Windows portability.+ * Fixed to never touch the git work tree or index file, instead using+ its own to commit to the github branch.++ -- Joey Hess <joeyh@debian.org> Mon, 17 Jun 2013 12:28:30 -0400++github-backup (1.20130614) unstable; urgency=low++ * Pass --ignore-removal to git-add, in preparation for a future change+ to its default behavior. Requires git 1.8.3. Closes: #711287++ -- Joey Hess <joeyh@debian.org> Fri, 14 Jun 2013 15:50:49 -0400++github-backup (1.20130414) experimental; urgency=low++ * Updated to use haskell-github 0.6.0, which supports pagination of queries+ Thanks to John Wiegley for making those changes.+ * Also backup closed issues. Thanks, John Wiegley.+ * cabal file no longer tries to list every source file, as that was+ error-prone, and I left some out.++ -- Joey Hess <joeyh@debian.org> Fri, 12 Apr 2013 18:33:11 -0400++github-backup (1.20120627) unstable; urgency=low++ * Rebuilt with new haskell-github, that works with the new version+ of http-conduit in Debian. Closes: #678787+ * Various updates to internal git and utility libraries shared with git-annex.++ -- Joey Hess <joeyh@debian.org> Wed, 27 Jun 2012 22:21:01 -0400++github-backup (1.20120314) unstable; urgency=low++ * First release.++ -- Joey Hess <joeyh@debian.org> Tue, 13 Mar 2012 20:22:43 -0400
+ COPYRIGHT view
@@ -0,0 +1,35 @@+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/+Source: native package++Files: *+Copyright: © 2010-2014 Joey Hess <joey@kitenet.net>+License: GPL-3++ The full text of version 3 of the GPL is distributed as doc/GPL in+ this package's source, or in /usr/share/common-licenses/GPL-3 on+ Debian systems.++Files: Utility/*+Copyright: 2012-2014 Joey Hess <joey@kitenet.net>+License: BSD-2-clause++License: BSD-2-clause+ Redistribution and use in source and binary forms, with or without+ modification, are permitted provided that the following conditions+ are met:+ 1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+ 2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+ .+ THIS SOFTWARE IS PROVIDED BY AUTHORS AND CONTRIBUTORS ``AS IS'' AND+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ SUCH DAMAGE.
Git.hs view
@@ -3,7 +3,7 @@ - This is written to be completely independant of git-annex and should be - suitable for other uses. -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -30,6 +30,8 @@ attributes, hookPath, assertLocal,+ adjustPath,+ relPath, ) where import Network.URI (uriPath, uriScheme, unEscapeString)@@ -58,7 +60,7 @@ repoLocation Repo { location = Local { worktree = Just dir } } = dir repoLocation Repo { location = Local { gitdir = dir } } = dir repoLocation Repo { location = LocalUnknown dir } = dir-repoLocation Repo { location = Unknown } = undefined+repoLocation Repo { location = Unknown } = error "unknown repoLocation" {- Path to a repository. For non-bare, this is the worktree, for bare, - it's the gitdir, and for URL repositories, is the path on the remote@@ -68,12 +70,12 @@ repoPath Repo { location = Local { worktree = Just d } } = d repoPath Repo { location = Local { gitdir = d } } = d repoPath Repo { location = LocalUnknown dir } = dir-repoPath Repo { location = Unknown } = undefined+repoPath Repo { location = Unknown } = error "unknown repoPath" {- Path to a local repository's .git directory. -} localGitDir :: Repo -> FilePath localGitDir Repo { location = Local { gitdir = d } } = d-localGitDir _ = undefined+localGitDir _ = error "unknown localGitDir" {- Some code needs to vary between URL and normal repos, - or bare and non-bare, these functions help with that. -}@@ -139,3 +141,29 @@ #else isexecutable f = isExecutable . fileMode <$> getFileStatus f #endif++{- Makes the path to a local Repo be relative to the cwd. -}+relPath :: Repo -> IO Repo+relPath = adjustPath torel+ where+ torel p = do+ p' <- relPathCwdToFile p+ if null p'+ then return "."+ else return p'++{- Adusts the path to a local Repo using the provided function. -}+adjustPath :: (FilePath -> IO FilePath) -> Repo -> IO Repo+adjustPath f r@(Repo { location = l@(Local { gitdir = d, worktree = w }) }) = do+ d' <- f d+ w' <- maybe (pure Nothing) (Just <$$> f) w+ return $ r + { location = l + { gitdir = d'+ , worktree = w'+ }+ }+adjustPath f r@(Repo { location = LocalUnknown d }) = do+ d' <- f d+ return $ r { location = LocalUnknown d' }+adjustPath _ r = pure r
Git/Branch.hs view
@@ -1,6 +1,6 @@ {- git branch stuff -- - Copyright 2011 Joey Hess <joey@kitenet.net>+ - Copyright 2011 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -37,14 +37,11 @@ {- The current branch, which may not really exist yet. -} currentUnsafe :: Repo -> IO (Maybe Git.Ref) currentUnsafe r = parse . firstLine- <$> pipeReadStrict [Param "symbolic-ref", Param $ fromRef Git.Ref.headRef] r+ <$> pipeReadStrict [Param "symbolic-ref", Param "-q", Param $ fromRef Git.Ref.headRef] r where parse l | null l = Nothing | otherwise = Just $ Git.Ref l--currentSha :: Repo -> IO (Maybe Git.Sha)-currentSha r = maybe (pure Nothing) (`Git.Ref.sha` r) =<< current r {- Checks if the second branch has any commits not present on the first - branch. -}
Git/BuildVersion.hs view
@@ -1,6 +1,6 @@ {- git build version -- - Copyright 2011 Joey Hess <joey@kitenet.net>+ - Copyright 2011 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/CatFile.hs view
@@ -1,6 +1,6 @@ {- git cat-file interface -- - Copyright 2011, 2013 Joey Hess <joey@kitenet.net>+ - Copyright 2011, 2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -110,4 +110,4 @@ parsemodefile b = let (modestr, file) = separate (== ' ') (decodeBS b) in (file, readmode modestr)- readmode = fst . fromMaybe (0, undefined) . headMaybe . readOct+ readmode = fromMaybe 0 . fmap fst . headMaybe . readOct
Git/Command.hs view
@@ -1,6 +1,6 @@ {- running git commands -- - Copyright 2010-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -16,7 +16,7 @@ {- Constructs a git command line operating on the specified repo. -} gitCommandLine :: [CommandParam] -> Repo -> [CommandParam]-gitCommandLine params r@(Repo { location = l@(Local _ _ ) }) =+gitCommandLine params r@(Repo { location = l@(Local { } ) }) = setdir : settree ++ gitGlobalOpts r ++ params where setdir = Param $ "--git-dir=" ++ gitdir l
Git/Config.hs view
@@ -1,6 +1,6 @@ {- git repository configuration handling -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -14,6 +14,7 @@ import Git import Git.Types import qualified Git.Construct+import qualified Git.Command import Utility.UserInfo {- Returns a single git config setting, or a default value if not set. -}@@ -66,10 +67,9 @@ home <- myHomeDir ifM (doesFileExist $ home </> ".gitconfig") ( do- repo <- Git.Construct.fromUnknown- repo' <- withHandle StdoutHandle createProcessSuccess p $- hRead repo- return $ Just repo'+ repo <- withHandle StdoutHandle createProcessSuccess p $+ hRead (Git.Construct.fromUnknown)+ return $ Just repo , return Nothing ) where@@ -194,3 +194,17 @@ , Param k , Param v ]++{- Unsets a git config setting, in both the git repo,+ - and the cached config in the Repo.+ -+ - If unsetting the config fails, including in a read-only repo, or+ - when the config is not set, returns Nothing.+ -}+unset :: String -> Repo -> IO (Maybe Repo)+unset k r = ifM (Git.Command.runBool ps r)+ ( return $ Just $ r { config = M.delete k (config r) }+ , return Nothing+ )+ where+ ps = [Param "config", Param "--unset-all", Param k]
Git/Construct.hs view
@@ -1,6 +1,6 @@ {- Construction of Git Repo objects -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -19,8 +19,8 @@ fromRemotes, fromRemoteLocation, repoAbsPath,- newFrom, checkForRepo,+ newFrom, ) where #ifndef mingw32_HOST_OS@@ -45,10 +45,10 @@ seekUp dir = do r <- checkForRepo dir case r of- Nothing -> case parentDir dir of+ Nothing -> case upFrom dir of Nothing -> return Nothing Just d -> seekUp d- Just loc -> Just <$> newFrom loc+ Just loc -> pure $ Just $ newFrom loc {- Local Repo constructor, accepts a relative or absolute path. -} fromPath :: FilePath -> IO Repo@@ -62,7 +62,7 @@ | otherwise = error $ "internal error, " ++ dir ++ " is not absolute" where- ret = newFrom . LocalUnknown+ ret = pure . newFrom . LocalUnknown {- Git always looks for "dir.git" in preference to - to "dir", even if dir ends in a "/". -} canondir = dropTrailingPathSeparator dir@@ -90,13 +90,13 @@ fromUrlStrict :: String -> IO Repo fromUrlStrict url | startswith "file://" url = fromAbsPath $ unEscapeString $ uriPath u- | otherwise = newFrom $ Url u+ | otherwise = pure $ newFrom $ Url u where u = fromMaybe bad $ parseURI url bad = error $ "bad url " ++ url {- Creates a repo that has an unknown location. -}-fromUnknown :: IO Repo+fromUnknown :: Repo fromUnknown = newFrom Unknown {- Converts a local Repo into a remote repo, using the reference repo@@ -153,7 +153,7 @@ fromRemotePath :: FilePath -> Repo -> IO Repo fromRemotePath dir repo = do dir' <- expandTilde dir- fromAbsPath $ repoPath repo </> dir'+ fromPath $ repoPath repo </> dir' {- Git remotes can have a directory that is specified relative - to the user's home directory, or that contains tilde expansions.@@ -223,8 +223,8 @@ gitdirprefix = "gitdir: " gitSignature file = doesFileExist $ dir </> file -newFrom :: RepoLocation -> IO Repo-newFrom l = return Repo+newFrom :: RepoLocation -> Repo+newFrom l = Repo { location = l , config = M.empty , fullconfig = M.empty@@ -233,5 +233,4 @@ , gitEnv = Nothing , gitGlobalOpts = [] }-
Git/DiffTreeItem.hs view
@@ -1,6 +1,6 @@ {- git diff-tree item -- - Copyright 2012 Joey Hess <joey@kitenet.net>+ - Copyright 2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/FilePath.hs view
@@ -5,7 +5,7 @@ - top of the repository even when run in a subdirectory. Adding some - types helps keep that straight. -- - Copyright 2012-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2012-2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -39,8 +39,7 @@ {- The input FilePath can be absolute, or relative to the CWD. -} toTopFilePath :: FilePath -> Git.Repo -> IO TopFilePath-toTopFilePath file repo = TopFilePath <$>- relPathDirToFile (repoPath repo) <$> absPath file+toTopFilePath file repo = TopFilePath <$> relPathDirToFile (repoPath repo) file {- The input FilePath must already be relative to the top of the git - repository -}
Git/HashObject.hs view
@@ -1,6 +1,6 @@ {- git hash-object interface -- - Copyright 2011-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2014 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -32,7 +32,7 @@ hashFile :: HashObjectHandle -> FilePath -> IO Sha hashFile h file = CoProcess.query h send receive where- send to = hPutStrLn to file+ send to = hPutStrLn to =<< absPath file receive from = getSha "hash-object" $ hGetLine from {- Injects a blob into git. Unfortunately, the current git-hash-object
Git/Queue.hs view
@@ -1,6 +1,6 @@ {- git repository command queue -- - Copyright 2010,2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010,2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/Ref.hs view
@@ -1,6 +1,6 @@ {- git ref stuff -- - Copyright 2011-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -87,6 +87,9 @@ Param $ fromRef branch] process [] = Nothing process s = Just $ Ref $ firstLine s++headSha :: Repo -> IO (Maybe Sha)+headSha = sha headRef {- List of (shas, branches) matching a given ref or refs. -} matching :: [Ref] -> Repo -> IO [(Sha, Branch)]
Git/Remote.hs view
@@ -1,6 +1,6 @@ {- git remote stuff -- - Copyright 2012 Joey Hess <joey@kitenet.net>+ - Copyright 2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/Sha.hs view
@@ -1,6 +1,6 @@ {- git SHA stuff -- - Copyright 2011 Joey Hess <joey@kitenet.net>+ - Copyright 2011 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/Types.hs view
@@ -1,6 +1,6 @@ {- git data types -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/UpdateIndex.hs view
@@ -1,6 +1,6 @@ {- git-update-index library -- - Copyright 2011-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/Url.hs view
@@ -1,6 +1,6 @@ {- git repository urls -- - Copyright 2010, 2011 Joey Hess <joey@kitenet.net>+ - Copyright 2010, 2011 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}
Git/Version.hs view
@@ -1,9 +1,11 @@ {- git versions -- - Copyright 2011, 2013 Joey Hess <joey@kitenet.net>+ - Copyright 2011, 2013 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}++{-# OPTIONS_GHC -fno-warn-tabs #-} module Git.Version ( installed,
Utility/Applicative.hs view
@@ -1,6 +1,6 @@ {- applicative stuff -- - Copyright 2012 Joey Hess <joey@kitenet.net>+ - Copyright 2012 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}
Utility/CoProcess.hs view
@@ -1,7 +1,7 @@ {- Interface for running a shell command as a coprocess, - sending it queries and getting back results. -- - Copyright 2012-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2012-2013 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}
Utility/Data.hs view
@@ -1,9 +1,11 @@ {- utilities for simple data types -- - Copyright 2013 Joey Hess <joey@kitenet.net>+ - Copyright 2013 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}++{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Data where
Utility/Directory.hs view
@@ -1,11 +1,12 @@ {- directory traversal and manipulation -- - Copyright 2011-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Directory where @@ -18,6 +19,7 @@ import Control.Concurrent import System.IO.Unsafe (unsafeInterleaveIO) import Data.Maybe+import Prelude #ifdef mingw32_HOST_OS import qualified System.Win32 as Win32@@ -111,7 +113,7 @@ -- But, mv will move into a directory if -- dest is one, which is not desired. whenM (isdir dest) rethrow- viaTmp mv dest undefined+ viaTmp mv dest "" where rethrow = throwM e mv tmp _ = do
Utility/DottedVersion.hs view
@@ -1,9 +1,11 @@ {- dotted versions, such as 1.0.1 -- - Copyright 2011-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}++{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.DottedVersion where
Utility/Env.hs view
@@ -1,11 +1,12 @@ {- portable environment variables -- - Copyright 2013 Joey Hess <joey@kitenet.net>+ - Copyright 2013 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Env where @@ -13,6 +14,7 @@ import Utility.Exception import Control.Applicative import Data.Maybe+import Prelude import qualified System.Environment as E import qualified System.SetEnv #else
Utility/Exception.hs view
@@ -1,11 +1,12 @@ {- Simple IO exception handling (and some more) -- - Copyright 2011-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2011-2015 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Exception ( module X,@@ -19,6 +20,7 @@ catchNonAsync, tryNonAsync, tryWhenExists,+ catchHardwareFault, ) where import Control.Monad.Catch as X hiding (Handler)@@ -26,7 +28,9 @@ import Control.Exception (IOException, AsyncException) import Control.Monad import Control.Monad.IO.Class (liftIO, MonadIO)-import System.IO.Error (isDoesNotExistError)+import System.IO.Error (isDoesNotExistError, ioeGetErrorType)+import GHC.IO.Exception (IOErrorType(..))+ import Utility.Data {- Catches IO errors and returns a Bool -}@@ -86,3 +90,12 @@ tryWhenExists a = do 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+ where+ onlyhw e+ | ioeGetErrorType e == HardwareFault = onhardwareerr e+ | otherwise = throwM e
Utility/FileMode.hs view
@@ -1,6 +1,6 @@ {- File mode utilities. -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}@@ -22,15 +22,12 @@ {- Applies a conversion function to a file's mode. -} modifyFileMode :: FilePath -> (FileMode -> FileMode) -> IO ()-modifyFileMode f convert = void $ modifyFileMode' f convert-modifyFileMode' :: FilePath -> (FileMode -> FileMode) -> IO FileMode-modifyFileMode' f convert = do+modifyFileMode f convert = do s <- getFileStatus f let old = fileMode s let new = convert old when (new /= old) $ setFileMode f new- return old {- Adds the specified FileModes to the input mode, leaving the rest - unchanged. -}@@ -41,14 +38,6 @@ removeModes :: [FileMode] -> FileMode -> FileMode removeModes ms m = m `intersectFileModes` complement (combineModes ms) -{- 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- writeModes :: [FileMode] writeModes = [ownerWriteMode, groupWriteMode, otherWriteMode] @@ -124,7 +113,7 @@ #endif combineModes :: [FileMode] -> FileMode-combineModes [] = undefined+combineModes [] = 0 combineModes [m] = m combineModes (m:ms) = foldl unionFileModes m ms @@ -151,7 +140,11 @@ - as writeFile. -} writeFileProtected :: FilePath -> String -> IO ()-writeFileProtected file content = withUmask 0o0077 $+writeFileProtected file content = writeFileProtected' file + (\h -> hPutStr h content)++writeFileProtected' :: FilePath -> (Handle -> IO ()) -> IO ()+writeFileProtected' file writer = withUmask 0o0077 $ withFile file WriteMode $ \h -> do void $ tryIO $ modifyFileMode file $ removeModes otherGroupModes- hPutStr h content+ writer h
Utility/FileSystemEncoding.hs view
@@ -1,11 +1,12 @@ {- GHC File system encoding handling. -- - Copyright 2012-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2012-2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.FileSystemEncoding ( fileEncoding,@@ -14,6 +15,8 @@ decodeBS, decodeW8, encodeW8,+ encodeW8NUL,+ decodeW8NUL, truncateFilePath, ) where @@ -25,6 +28,7 @@ import qualified Data.Hash.MD5 as MD5 import Data.Word import Data.Bits.Utils+import Data.List.Utils import qualified Data.ByteString.Lazy as L #ifdef mingw32_HOST_OS import qualified Data.ByteString.Lazy.UTF8 as L8@@ -89,6 +93,9 @@ - w82c produces a String, which may contain Chars that are invalid - unicode. From there, this is really a simple matter of applying the - file system encoding, only complicated by GHC's interface to doing so.+ -+ - Note that the encoding stops at any NUL in the input. FilePaths+ - do not normally contain embedded NUL, but Haskell Strings may. -} {-# NOINLINE encodeW8 #-} encodeW8 :: [Word8] -> FilePath@@ -100,6 +107,17 @@ - represent the FilePath on disk. -} decodeW8 :: FilePath -> [Word8] decodeW8 = s2w8 . _encodeFilePath++{- Like encodeW8 and decodeW8, but NULs are passed through unchanged. -}+encodeW8NUL :: [Word8] -> FilePath+encodeW8NUL = join nul . map encodeW8 . split (s2w8 nul)+ where+ nul = ['\NUL']++decodeW8NUL :: FilePath -> [Word8]+decodeW8NUL = join (s2w8 nul) . map decodeW8 . split nul+ where+ nul = ['\NUL'] {- Truncates a FilePath to the given number of bytes (or less), - as represented on disk.
Utility/Misc.hs view
@@ -1,28 +1,30 @@ {- misc utility functions -- - Copyright 2010-2011 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2011 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Misc where +import Utility.FileSystemEncoding+import Utility.Monad+ import System.IO import Control.Monad import Foreign import Data.Char import Data.List-import Control.Applicative import System.Exit #ifndef mingw32_HOST_OS import System.Posix.Process (getAnyProcessStatus) import Utility.Exception #endif--import Utility.FileSystemEncoding-import Utility.Monad+import Control.Applicative+import Prelude {- A version of hgetContents that is not lazy. Ensures file is - all read before it gets closed. -}
Utility/Monad.hs view
@@ -1,9 +1,11 @@ {- monadic stuff -- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}++{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Monad where
Utility/PartialPrelude.hs view
@@ -5,6 +5,8 @@ - them being accidentially used. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Utility.PartialPrelude where import qualified Data.Maybe
Utility/Path.hs view
@@ -1,11 +1,12 @@ {- path manipulation -- - Copyright 2010-2014 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE PackageImports, CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Path where @@ -16,6 +17,7 @@ import Data.Maybe import Data.Char import Control.Applicative+import Prelude #ifdef mingw32_HOST_OS import qualified System.FilePath.Posix as Posix@@ -66,7 +68,7 @@ absPathFrom dir path = simplifyPath (combine dir path) {- On Windows, this converts the paths to unix-style, in order to run- - MissingH's absNormPath on them. Resulting path will use / separators. -}+ - MissingH's absNormPath on them. -} absNormPathUnix :: FilePath -> FilePath -> Maybe FilePath #ifndef mingw32_HOST_OS absNormPathUnix dir path = MissingH.absNormPath dir path@@ -77,11 +79,15 @@ todos = replace "/" "\\" #endif +{- takeDirectory "foo/bar/" is "foo/bar". This instead yields "foo" -}+parentDir :: FilePath -> FilePath+parentDir = takeDirectory . dropTrailingPathSeparator+ {- Just the parent directory of a path, or Nothing if the path has no- - parent (ie for "/") -}-parentDir :: FilePath -> Maybe FilePath-parentDir dir- | null dirs = Nothing+- parent (ie for "/" or ".") -}+upFrom :: FilePath -> Maybe FilePath+upFrom dir+ | length dirs < 2 = Nothing | otherwise = Just $ joinDrive drive (join s $ init dirs) where -- on Unix, the drive will be "/" when the dir is absolute, otherwise ""@@ -89,13 +95,13 @@ dirs = filter (not . null) $ split s path s = [pathSeparator] -prop_parentDir_basics :: FilePath -> Bool-prop_parentDir_basics dir+prop_upFrom_basics :: FilePath -> Bool+prop_upFrom_basics dir | null dir = True- | dir == "/" = parentDir dir == Nothing+ | dir == "/" = p == Nothing | otherwise = p /= Just dir where- p = parentDir dir+ p = upFrom dir {- Checks if the first FilePath is, or could be said to contain the second. - For example, "foo/" contains "foo/bar". Also, "foo", "./foo", "foo/" etc@@ -124,14 +130,25 @@ - relPathCwdToFile "/tmp/foo/bar" == "" -} relPathCwdToFile :: FilePath -> IO FilePath-relPathCwdToFile f = relPathDirToFile <$> getCurrentDirectory <*> absPath f+relPathCwdToFile f = do+ c <- getCurrentDirectory+ relPathDirToFile c f -{- Constructs a relative path from a directory to a file.+{- Constructs a relative path from a directory to a file. -}+relPathDirToFile :: FilePath -> FilePath -> IO FilePath+relPathDirToFile from to = relPathDirToFileAbs <$> absPath from <*> absPath to++{- This requires the first path to be absolute, and the+ - second path cannot contain ../ or ./ -- - Both must be absolute, and cannot contain .. etc. (eg use absPath first).+ - On Windows, if the paths are on different drives,+ - a relative path is not possible and the path is simply+ - returned as-is. -}-relPathDirToFile :: FilePath -> FilePath -> FilePath-relPathDirToFile from to = join s $ dotdots ++ uncommon+relPathDirToFileAbs :: FilePath -> FilePath -> FilePath+relPathDirToFileAbs from to+ | takeDrive from /= takeDrive to = to+ | otherwise = join s $ dotdots ++ uncommon where s = [pathSeparator] pfrom = split s from@@ -144,10 +161,11 @@ prop_relPathDirToFile_basics :: FilePath -> FilePath -> Bool prop_relPathDirToFile_basics from to+ | null from || null to = True | from == to = null r | otherwise = not (null r) where- r = relPathDirToFile from to + r = relPathDirToFileAbs from to prop_relPathDirToFile_regressionTest :: Bool prop_relPathDirToFile_regressionTest = same_dir_shortcurcuits_at_difference@@ -156,22 +174,31 @@ - location, but it's not really the same directory. - Code used to get this wrong. -} same_dir_shortcurcuits_at_difference =- relPathDirToFile (joinPath [pathSeparator : "tmp", "r", "lll", "xxx", "yyy", "18"])+ relPathDirToFileAbs (joinPath [pathSeparator : "tmp", "r", "lll", "xxx", "yyy", "18"]) (joinPath [pathSeparator : "tmp", "r", ".git", "annex", "objects", "18", "gk", "SHA256-foo", "SHA256-foo"]) == joinPath ["..", "..", "..", "..", ".git", "annex", "objects", "18", "gk", "SHA256-foo", "SHA256-foo"] {- Given an original list of paths, and an expanded list derived from it,- - generates a list of lists, where each sublist corresponds to one of the- - original paths. When the original path is a directory, any items- - in the expanded list that are contained in that directory will appear in- - its segment.+ - which may be arbitrarily reordered, generates a list of lists, where+ - each sublist corresponds to one of the original paths.+ -+ - When the original path is a directory, any items in the expanded list+ - that are contained in that directory will appear in its segment.+ -+ - The order of the original list of paths is attempted to be preserved in+ - the order of the returned segments. However, doing so has a O^NM+ - growth factor. So, if the original list has more than 100 paths on it,+ - we stop preserving ordering at that point. Presumably a user passing+ - that many paths in doesn't care too much about order of the later ones. -} segmentPaths :: [FilePath] -> [FilePath] -> [[FilePath]] segmentPaths [] new = [new] segmentPaths [_] new = [new] -- optimisation-segmentPaths (l:ls) new = [found] ++ segmentPaths ls rest+segmentPaths (l:ls) new = found : segmentPaths ls rest where- (found, rest)=partition (l `dirContains`) new+ (found, rest) = if length ls < 100+ then partition (l `dirContains`) new+ else break (\p -> not (l `dirContains` p)) new {- This assumes that it's cheaper to call segmentPaths on the result, - than it would be to run the action separately with each path. In@@ -185,7 +212,7 @@ relHome path = do home <- myHomeDir return $ if dirContains home path- then "~/" ++ relPathDirToFile home path+ then "~/" ++ relPathDirToFileAbs home path else path {- Checks if a command is available in PATH.
Utility/PosixFiles.hs view
@@ -2,12 +2,13 @@ - - This is like System.PosixCompat.Files, except with a fixed rename. -- - Copyright 2014 Joey Hess <joey@kitenet.net>+ - Copyright 2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.PosixFiles ( module X,
Utility/Process.hs view
@@ -1,12 +1,13 @@ {- System.Process enhancements, including additional ways of running - processes, and logging. -- - Copyright 2012 Joey Hess <id@joeyh.name>+ - Copyright 2012-2015 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP, Rank2Types #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Process ( module X,@@ -25,14 +26,16 @@ processTranscript, processTranscript', withHandle,- withBothHandles,+ withIOHandles,+ withOEHandles, withQuietOutput,+ feedWithQuietOutput, createProcess, startInteractiveProcess, stdinHandle, stdoutHandle, stderrHandle,- bothHandles,+ ioHandles, processHandle, devNull, ) where@@ -52,6 +55,7 @@ import Control.Applicative #endif import Data.Maybe+import Prelude import Utility.Misc import Utility.Exception@@ -61,8 +65,8 @@ data StdHandle = StdinHandle | StdoutHandle | StderrHandle deriving (Eq) -{- Normally, when reading from a process, it does not need to be fed any- - standard input. -}+-- | Normally, when reading from a process, it does not need to be fed any+-- standard input. readProcess :: FilePath -> [String] -> IO String readProcess cmd args = readProcessEnv cmd args Nothing @@ -80,9 +84,8 @@ hClose h return output -{- Runs an action to write to a process on its stdin, - - returns its output, and also allows specifying the environment.- -}+-- | Runs an action to write to a process on its stdin, +-- returns its output, and also allows specifying the environment. writeReadProcessEnv :: FilePath -> [String]@@ -122,8 +125,8 @@ , env = environ } -{- Waits for a ProcessHandle, and throws an IOError if the process- - did not exit successfully. -}+-- | Waits for a ProcessHandle, and throws an IOError if the process+-- did not exit successfully. forceSuccessProcess :: CreateProcess -> ProcessHandle -> IO () forceSuccessProcess p pid = do code <- waitForProcess pid@@ -131,10 +134,10 @@ ExitSuccess -> return () ExitFailure n -> fail $ showCmd p ++ " exited " ++ show n -{- Waits for a ProcessHandle and returns True if it exited successfully.- - Note that using this with createProcessChecked will throw away- - the Bool, and is only useful to ignore the exit code of a process,- - while still waiting for it. -}+-- | Waits for a ProcessHandle and returns True if it exited successfully.+-- Note that using this with createProcessChecked will throw away+-- the Bool, and is only useful to ignore the exit code of a process,+-- while still waiting for it. -} checkSuccessProcess :: ProcessHandle -> IO Bool checkSuccessProcess pid = do code <- waitForProcess pid@@ -145,13 +148,13 @@ void $ waitForProcess pid return True -{- Runs createProcess, then an action on its handles, and then- - forceSuccessProcess. -}+-- | Runs createProcess, then an action on its handles, and then+-- forceSuccessProcess. createProcessSuccess :: CreateProcessRunner createProcessSuccess p a = createProcessChecked (forceSuccessProcess p) p a -{- Runs createProcess, then an action on its handles, and then- - a checker action on its exit code, which must wait for the process. -}+-- | Runs createProcess, then an action on its handles, and then+-- a checker action on its exit code, which must wait for the process. createProcessChecked :: (ProcessHandle -> IO b) -> CreateProcessRunner createProcessChecked checker p a = do t@(_, _, _, pid) <- createProcess p@@ -159,14 +162,14 @@ _ <- checker pid either E.throw return r -{- Leaves the process running, suitable for lazy streaming.- - Note: Zombies will result, and must be waited on. -}+-- | Leaves the process running, suitable for lazy streaming.+-- Note: Zombies will result, and must be waited on. createBackgroundProcess :: CreateProcessRunner createBackgroundProcess p a = a =<< createProcess p -{- Runs a process, optionally feeding it some input, and- - returns a transcript combining its stdout and stderr, and- - whether it succeeded or failed. -}+-- | Runs a process, optionally feeding it some input, and+-- 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 @@ -230,9 +233,9 @@ hClose inh writeinput Nothing _ = return () -{- Runs a CreateProcessRunner, on a CreateProcess structure, that- - is adjusted to pipe only from/to a single StdHandle, and passes- - the resulting Handle to an action. -}+-- | Runs a CreateProcessRunner, on a CreateProcess structure, that+-- is adjusted to pipe only from/to a single StdHandle, and passes+-- the resulting Handle to an action. withHandle :: StdHandle -> CreateProcessRunner@@ -254,13 +257,13 @@ | h == StderrHandle = (stderrHandle, base { std_err = CreatePipe }) -{- Like withHandle, but passes (stdin, stdout) handles to the action. -}-withBothHandles+-- | Like withHandle, but passes (stdin, stdout) handles to the action.+withIOHandles :: CreateProcessRunner -> CreateProcess -> ((Handle, Handle) -> IO a) -> IO a-withBothHandles creator p a = creator p' $ a . bothHandles+withIOHandles creator p a = creator p' $ a . ioHandles where p' = p { std_in = CreatePipe@@ -268,8 +271,22 @@ , std_err = Inherit } -{- Forces the CreateProcessRunner to run quietly;- - both stdout and stderr are discarded. -}+-- | Like withHandle, but passes (stdout, stderr) handles to the action.+withOEHandles+ :: CreateProcessRunner+ -> CreateProcess+ -> ((Handle, Handle) -> IO a)+ -> IO a+withOEHandles creator p a = creator p' $ a . oeHandles+ where+ p' = p+ { std_in = Inherit+ , std_out = CreatePipe+ , std_err = CreatePipe+ }++-- | Forces the CreateProcessRunner to run quietly;+-- both stdout and stderr are discarded. withQuietOutput :: CreateProcessRunner -> CreateProcess@@ -281,6 +298,21 @@ } creator p' $ const $ return () +-- | Stdout and stderr are discarded, while the process is fed stdin+-- from the handle.+feedWithQuietOutput+ :: CreateProcessRunner+ -> CreateProcess+ -> (Handle -> IO a)+ -> IO a+feedWithQuietOutput creator p a = withFile devNull WriteMode $ \nullh -> do+ let p' = p+ { std_in = CreatePipe+ , std_out = UseHandle nullh+ , std_err = UseHandle nullh+ }+ creator p' $ a . stdinHandle+ devNull :: FilePath #ifndef mingw32_HOST_OS devNull = "/dev/null"@@ -288,11 +320,11 @@ devNull = "NUL" #endif -{- Extract a desired handle from createProcess's tuple.- - These partial functions are safe as long as createProcess is run- - with appropriate parameters to set up the desired handle.- - Get it wrong and the runtime crash will always happen, so should be- - easily noticed. -}+-- | Extract a desired handle from createProcess's tuple.+-- These partial functions are safe as long as createProcess is run+-- with appropriate parameters to set up the desired handle.+-- Get it wrong and the runtime crash will always happen, so should be+-- easily noticed. type HandleExtractor = (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> Handle stdinHandle :: HandleExtractor stdinHandle (Just h, _, _, _) = h@@ -303,14 +335,17 @@ stderrHandle :: HandleExtractor stderrHandle (_, _, Just h, _) = h stderrHandle _ = error "expected stderrHandle"-bothHandles :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> (Handle, Handle)-bothHandles (Just hin, Just hout, _, _) = (hin, hout)-bothHandles _ = error "expected bothHandles"+ioHandles :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> (Handle, Handle)+ioHandles (Just hin, Just hout, _, _) = (hin, hout)+ioHandles _ = error "expected ioHandles"+oeHandles :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> (Handle, Handle)+oeHandles (_, Just hout, Just herr, _) = (hout, herr)+oeHandles _ = error "expected oeHandles" processHandle :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> ProcessHandle processHandle (_, _, _, pid) = pid -{- Debugging trace for a CreateProcess. -}+-- | Debugging trace for a CreateProcess. debugProcess :: CreateProcess -> IO () debugProcess p = do debugM "Utility.Process" $ unwords@@ -326,15 +361,15 @@ piped Inherit = False piped _ = True -{- Shows the command that a CreateProcess will run. -}+-- | Shows the command that a CreateProcess will run. showCmd :: CreateProcess -> String showCmd = go . cmdspec where go (ShellCommand s) = s go (RawCommand c ps) = c ++ " " ++ show ps -{- Starts an interactive process. Unlike runInteractiveProcess in- - System.Process, stderr is inherited. -}+-- | Starts an interactive process. Unlike runInteractiveProcess in+-- System.Process, stderr is inherited. startInteractiveProcess :: FilePath -> [String]@@ -350,7 +385,8 @@ (Just from, Just to, _, pid) <- createProcess p return (pid, to, from) -{- Wrapper around System.Process function that does debug logging. -}+-- | Wrapper around 'System.Process.createProcess' from System.Process,+-- that does debug logging. createProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) createProcess p = do debugProcess p
Utility/SafeCommand.hs view
@@ -1,84 +1,93 @@ {- safely running shell commands -- - Copyright 2010-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2015 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Utility.SafeCommand where import System.Exit import Utility.Process import Data.String.Utils-import Control.Applicative import System.FilePath import Data.Char+import Control.Applicative+import Prelude -{- A type for parameters passed to a shell command. A command can- - be passed either some Params (multiple parameters can be included,- - whitespace-separated, or a single Param (for when parameters contain- - whitespace), or a File.- -}-data CommandParam = Params String | Param String | File FilePath+-- | Parameters that can be passed to a shell command.+data CommandParam+ = Param String -- ^ A parameter+ | File FilePath -- ^ The name of a file deriving (Eq, Show, Ord) -{- Used to pass a list of CommandParams to a function that runs- - a command and expects Strings. -}+-- | Used to pass a list of CommandParams to a function that runs+-- a command and expects Strings. -} toCommand :: [CommandParam] -> [String]-toCommand = concatMap unwrap+toCommand = map unwrap where- unwrap (Param s) = [s]- unwrap (Params s) = filter (not . null) (split " " s)+ unwrap (Param s) = s -- Files that start with a non-alphanumeric that is not a path -- separator are modified to avoid the command interpreting them as -- options or other special constructs. unwrap (File s@(h:_))- | isAlphaNum h || h `elem` pathseps = [s]- | otherwise = ["./" ++ s]- unwrap (File s) = [s]+ | isAlphaNum h || h `elem` pathseps = s+ | otherwise = "./" ++ s+ unwrap (File s) = s -- '/' is explicitly included because it's an alternative -- path separator on Windows. pathseps = pathSeparator:"./" -{- Run a system command, and returns True or False- - if it succeeded or failed.- -}+-- | Run a system command, and returns True or False if it succeeded or failed.+--+-- This and other command running functions in this module log the commands+-- run at debug level, using System.Log.Logger. boolSystem :: FilePath -> [CommandParam] -> IO Bool-boolSystem command params = boolSystemEnv command params Nothing+boolSystem command params = boolSystem' command params id -boolSystemEnv :: FilePath -> [CommandParam] -> Maybe [(String, String)] -> IO Bool-boolSystemEnv command params environ = dispatch <$> safeSystemEnv command params environ+boolSystem' :: FilePath -> [CommandParam] -> (CreateProcess -> CreateProcess) -> IO Bool+boolSystem' command params mkprocess = dispatch <$> safeSystem' command params mkprocess where dispatch ExitSuccess = True dispatch _ = False -{- Runs a system command, returning the exit status. -}+boolSystemEnv :: FilePath -> [CommandParam] -> Maybe [(String, String)] -> IO Bool+boolSystemEnv command params environ = boolSystem' command params $+ \p -> p { env = environ }++-- | Runs a system command, returning the exit status. safeSystem :: FilePath -> [CommandParam] -> IO ExitCode-safeSystem command params = safeSystemEnv command params Nothing+safeSystem command params = safeSystem' command params id -safeSystemEnv :: FilePath -> [CommandParam] -> Maybe [(String, String)] -> IO ExitCode-safeSystemEnv command params environ = do- (_, _, _, pid) <- createProcess (proc command $ toCommand params)- { env = environ }+safeSystem' :: FilePath -> [CommandParam] -> (CreateProcess -> CreateProcess) -> IO ExitCode+safeSystem' command params mkprocess = do+ (_, _, _, pid) <- createProcess p waitForProcess pid+ where+ p = mkprocess $ proc command (toCommand params) -{- Wraps a shell command line inside sh -c, allowing it to be run in a- - login shell that may not support POSIX shell, eg csh. -}+safeSystemEnv :: FilePath -> [CommandParam] -> Maybe [(String, String)] -> IO ExitCode+safeSystemEnv command params environ = safeSystem' command params $ + \p -> p { env = environ }++-- | Wraps a shell command line inside sh -c, allowing it to be run in a+-- login shell that may not support POSIX shell, eg csh. shellWrap :: String -> String shellWrap cmdline = "sh -c " ++ shellEscape cmdline -{- Escapes a filename or other parameter to be safely able to be exposed to- - the shell.- -- - This method works for POSIX shells, as well as other shells like csh.- -}+-- | Escapes a filename or other parameter to be safely able to be exposed to+-- the shell.+--+-- This method works for POSIX shells, as well as other shells like csh. shellEscape :: String -> String shellEscape f = "'" ++ escaped ++ "'" where -- replace ' with '"'"' escaped = join "'\"'\"'" $ split "'" f -{- Unescapes a set of shellEscaped words or filenames. -}+-- | Unescapes a set of shellEscaped words or filenames. shellUnEscape :: String -> [String] shellUnEscape [] = [] shellUnEscape s = word : shellUnEscape rest@@ -95,25 +104,32 @@ | c == q = findword w cs | otherwise = inquote q (w++[c]) cs -{- For quickcheck. -}+-- | 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 -{- Segements a list of filenames into groups that are all below the manximum- - command-line length limit. Does not preserve order. -}-segmentXargs :: [FilePath] -> [[FilePath]]-segmentXargs l = go l [] 0 []+-- | Segments a list of filenames into groups that are all below the maximum+-- command-line length limit.+segmentXargsOrdered :: [FilePath] -> [[FilePath]]+segmentXargsOrdered = reverse . map reverse . segmentXargsUnordered++-- | Not preserving order is a little faster, and streams better when+-- there are a great many filenames.+segmentXargsUnordered :: [FilePath] -> [[FilePath]]+segmentXargsUnordered l = go l [] 0 [] where- go [] c _ r = c:r+ go [] c _ r = (c:r) go (f:fs) c accumlen r- | len < maxlen && newlen > maxlen = go (f:fs) [] 0 (c:r)+ | newlen > maxlen && len < maxlen = go (f:fs) [] 0 (c:r) | otherwise = go fs (f:c) newlen r where len = length f newlen = accumlen + len - {- 10k of filenames per command, well under Linux's 20k limit;- - allows room for other parameters etc. -}+ {- 10k of filenames per command, well under 100k limit+ - of Linux (and OSX has a similar limit);+ - allows room for other parameters etc. Also allows for+ - eg, multibyte characters. -} maxlen = 10240
Utility/Tmp.hs view
@@ -1,11 +1,12 @@ {- Temporary files and directories. -- - Copyright 2010-2013 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2013 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Tmp where
Utility/URI.hs view
@@ -1,6 +1,6 @@ {- Network.URI -- - Copyright 2014 Joey Hess <joey@kitenet.net>+ - Copyright 2014 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}
Utility/UserInfo.hs view
@@ -1,11 +1,12 @@ {- user info -- - Copyright 2012 Joey Hess <joey@kitenet.net>+ - Copyright 2012 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -} {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.UserInfo ( myHomeDir,@@ -13,12 +14,13 @@ myUserGecos, ) where +import Utility.Env+ import System.PosixCompat #ifndef mingw32_HOST_OS import Control.Applicative #endif--import Utility.Env+import Prelude {- Current user's home directory. -
debian/changelog view
@@ -1,3 +1,12 @@+github-backup (1.20150617) unstable; urgency=medium++ * Add missing build deps for windows to cabal file.+ Thanks, Jeff Segal.+ * Various updates to internal git and utility libraries shared+ with git-annex.++ -- Joey Hess <id@joeyh.name> Wed, 17 Jun 2015 14:44:14 -0400+ github-backup (1.20150106) unstable; urgency=medium * Fix build with process 1.2.1.0.
debian/rules view
@@ -8,7 +8,3 @@ %: dh $@--# Not intended for use by anyone except the author.-announcedir:- @echo ${HOME}/src/joeywiki/code/github-backup/news
github-backup.cabal view
@@ -1,13 +1,14 @@ Name: github-backup-Version: 1.20150106+Version: 1.20150617 Cabal-Version: >= 1.8-License: GPL Maintainer: Joey Hess <joey@kitenet.net> Author: Joey Hess Stability: Stable Copyright: 2012 Joey Hess-License-File: GPL+License: GPL-3+License-File: COPYRIGHT Build-Type: Custom+Extra-Source-Files: CHANGELOG Homepage: https://github.com/joeyh/github-backup Category: Utility Synopsis: backs up everything github knows about a repository, to the repository@@ -25,7 +26,7 @@ Executable github-backup Main-Is: github-backup.hs- GHC-Options: -Wall+ GHC-Options: -Wall -fno-warn-tabs Build-Depends: MissingH, hslogger, directory, filepath, containers, mtl, network, exceptions, transformers, unix-compat, bytestring, IfElse, pretty-show, text, process, optparse-applicative,@@ -34,6 +35,8 @@ if (! os(windows)) Build-Depends: unix+ else+ Build-Depends: Win32, setenv, utf8-string if flag(network-uri) Build-Depends: network-uri (>= 2.6), network (>= 2.6)@@ -49,6 +52,8 @@ if (! os(windows)) Build-Depends: unix+ else+ Build-Depends: Win32, setenv, utf8-string if flag(network-uri) Build-Depends: network-uri (>= 2.6), network (>= 2.6)
github-backup.hs view
@@ -310,7 +310,7 @@ fs <- filter (not . dirCruft) <$> dirContentsRecursive dir forM_ fs $ \f -> do sha <- hashFile h f- let path = asTopFilePath (relPathDirToFile dir f)+ path <- asTopFilePath <$> relPathDirToFile dir f streamer $ Git.UpdateIndex.updateIndexLine sha Git.Types.FileBlob path