git-annex/Git.hs

139 lines
3.7 KiB
Haskell
Raw Normal View History

2010-10-12 03:22:38 +00:00
{- git repository handling
-
- This is written to be completely independant of git-annex and should be
- suitable for other uses.
-
- Copyright 2010, 2011 Joey Hess <joey@kitenet.net>
2010-10-27 20:53:54 +00:00
-
- Licensed under the GNU GPL version 3 or higher.
2010-10-14 06:36:41 +00:00
-}
2010-10-10 01:06:46 +00:00
module Git (
2011-12-14 19:30:14 +00:00
Repo(..),
Ref(..),
Branch,
Sha,
Tag,
2010-10-22 18:05:30 +00:00
repoIsUrl,
2010-10-22 17:40:19 +00:00
repoIsSsh,
2011-08-16 23:23:56 +00:00
repoIsHttp,
repoIsLocalBare,
2010-10-14 06:36:41 +00:00
repoDescribe,
repoLocation,
2010-10-14 06:36:41 +00:00
workTree,
2010-10-31 19:38:47 +00:00
gitDir,
2010-10-28 16:15:21 +00:00
configTrue,
2010-10-14 06:36:41 +00:00
attributes,
hookPath,
assertLocal,
2010-10-11 21:52:46 +00:00
) where
2010-10-10 01:06:46 +00:00
2011-12-13 19:22:43 +00:00
import qualified Data.Map as M
2010-11-06 21:07:11 +00:00
import Data.Char
import Network.URI (uriPath, uriScheme, unEscapeString)
2012-03-14 16:17:38 +00:00
import System.Posix.Files
2010-10-16 20:20:49 +00:00
import Common
import Git.Types
2012-03-14 16:17:38 +00:00
import Utility.FileMode
{- User-visible description of a git repo. -}
2010-10-31 19:38:47 +00:00
repoDescribe :: Repo -> String
repoDescribe Repo { remoteName = Just name } = name
repoDescribe Repo { location = Url url } = show url
repoDescribe Repo { location = Dir dir } = dir
repoDescribe Repo { location = Unknown } = "UNKNOWN"
2010-10-13 18:40:56 +00:00
{- Location of the repo, either as a path or url. -}
repoLocation :: Repo -> String
repoLocation Repo { location = Url url } = show url
repoLocation Repo { location = Dir dir } = dir
repoLocation Repo { location = Unknown } = undefined
2010-10-22 18:05:30 +00:00
{- Some code needs to vary between URL and normal repos,
2010-10-22 16:38:20 +00:00
- or bare and non-bare, these functions help with that. -}
2010-10-31 19:38:47 +00:00
repoIsUrl :: Repo -> Bool
repoIsUrl Repo { location = Url _ } = True
repoIsUrl _ = False
2010-10-31 19:38:47 +00:00
repoIsSsh :: Repo -> Bool
repoIsSsh Repo { location = Url url }
2011-12-14 19:30:14 +00:00
| scheme == "ssh:" = True
-- git treats these the same as ssh
2011-12-14 19:30:14 +00:00
| scheme == "git+ssh:" = True
| scheme == "ssh+git:" = True
| otherwise = False
2011-12-14 19:30:14 +00:00
where
scheme = uriScheme url
repoIsSsh _ = False
2011-08-16 23:23:56 +00:00
repoIsHttp :: Repo -> Bool
repoIsHttp Repo { location = Url url }
| uriScheme url == "http:" = True
| uriScheme url == "https:" = True
| otherwise = False
repoIsHttp _ = False
configAvail ::Repo -> Bool
configAvail Repo { config = c } = c /= M.empty
repoIsLocalBare :: Repo -> Bool
repoIsLocalBare r@(Repo { location = Dir _ }) = configAvail r && configBare r
repoIsLocalBare _ = False
2010-10-31 19:38:47 +00:00
assertLocal :: Repo -> a -> a
2012-03-16 05:59:07 +00:00
assertLocal repo action
| repoIsUrl repo = error $ unwords
[ "acting on non-local git repo"
, repoDescribe repo
, "not supported"
]
| otherwise = action
configBare :: Repo -> Bool
configBare repo = maybe unknown (fromMaybe False . configTrue) $
M.lookup "core.bare" $ config repo
2011-05-15 16:25:58 +00:00
where
unknown = error $ "it is not known if git repo " ++
2010-11-06 21:07:11 +00:00
repoDescribe repo ++
" is a bare repository; config not read"
2010-10-11 21:52:46 +00:00
{- Path to a repository's gitattributes file. -}
attributes :: Repo -> FilePath
attributes repo
| configBare repo = workTree repo ++ "/info/.gitattributes"
2010-11-06 21:07:11 +00:00
| otherwise = workTree repo ++ "/.gitattributes"
2010-10-10 06:29:58 +00:00
2011-08-19 16:59:07 +00:00
{- Path to a repository's .git directory. -}
gitDir :: Repo -> FilePath
2010-10-31 19:38:47 +00:00
gitDir repo
2011-08-19 16:59:07 +00:00
| configBare repo = workTree repo
| otherwise = workTree repo </> ".git"
2010-10-10 06:29:58 +00:00
{- Path to a given hook script in a repository, only if the hook exists
- and is executable. -}
hookPath :: String -> Repo -> IO (Maybe FilePath)
hookPath script repo = do
let hook = gitDir repo </> "hooks" </> script
2012-03-16 05:59:07 +00:00
ifM (catchBoolIO $ isexecutable hook)
( return $ Just hook , return Nothing )
where
isexecutable f = isExecutable . fileMode <$> getFileStatus f
{- Path to a repository's --work-tree, that is, its top.
-
- Note that for URL repositories, this is the path on the remote host. -}
2010-10-14 06:36:41 +00:00
workTree :: Repo -> FilePath
workTree Repo { location = Url u } = unEscapeString $ uriPath u
2011-12-14 19:30:14 +00:00
workTree Repo { location = Dir d } = d
workTree Repo { location = Unknown } = undefined
2010-10-12 04:53:42 +00:00
{- Checks if a string from git config is a true value. -}
configTrue :: String -> Maybe Bool
configTrue s
| s' == "true" = Just True
| s' == "false" = Just False
| otherwise = Nothing
where
s' = map toLower s