better git repo querying and bare repo detection
This commit is contained in:
parent
b430f55b80
commit
10b7c405fa
1 changed files with 38 additions and 29 deletions
67
GitRepo.hs
67
GitRepo.hs
|
@ -38,7 +38,6 @@ import Utility
|
||||||
data GitRepo =
|
data GitRepo =
|
||||||
LocalGitRepo {
|
LocalGitRepo {
|
||||||
top :: FilePath,
|
top :: FilePath,
|
||||||
bare :: Bool,
|
|
||||||
config :: Map String String
|
config :: Map String String
|
||||||
} | RemoteGitRepo {
|
} | RemoteGitRepo {
|
||||||
url :: String,
|
url :: String,
|
||||||
|
@ -46,24 +45,20 @@ data GitRepo =
|
||||||
config :: Map String String
|
config :: Map String String
|
||||||
} deriving (Show, Read, Eq)
|
} deriving (Show, Read, Eq)
|
||||||
|
|
||||||
{- Local GitRepo constructor. -}
|
{- Local GitRepo constructor. Can optionally query the repo for its config. -}
|
||||||
gitRepoFromPath :: FilePath -> IO GitRepo
|
gitRepoFromPath :: FilePath -> Bool -> IO GitRepo
|
||||||
gitRepoFromPath dir = do
|
gitRepoFromPath dir query = do
|
||||||
b <- isBareRepo dir
|
|
||||||
|
|
||||||
let r = LocalGitRepo {
|
let r = LocalGitRepo {
|
||||||
top = dir,
|
top = dir,
|
||||||
bare = b,
|
|
||||||
config = Map.empty
|
config = Map.empty
|
||||||
}
|
}
|
||||||
r' <- gitConfigRead r
|
if (query)
|
||||||
|
then gitConfigRead r
|
||||||
|
else return r
|
||||||
|
|
||||||
return r'
|
{- Remote GitRepo constructor. Throws exception on invalid url. -}
|
||||||
|
gitRepoFromUrl :: String -> Bool -> IO GitRepo
|
||||||
{- Remote GitRepo constructor. Note that remote repo config is not read.
|
gitRepoFromUrl url query = do
|
||||||
- Throws exception on invalid url. -}
|
|
||||||
gitRepoFromUrl :: String -> IO GitRepo
|
|
||||||
gitRepoFromUrl url = do
|
|
||||||
return $ RemoteGitRepo {
|
return $ RemoteGitRepo {
|
||||||
url = url,
|
url = url,
|
||||||
top = path url,
|
top = path url,
|
||||||
|
@ -71,8 +66,11 @@ gitRepoFromUrl url = do
|
||||||
}
|
}
|
||||||
where path url = uriPath $ fromJust $ parseURI url
|
where path url = uriPath $ fromJust $ parseURI url
|
||||||
|
|
||||||
{- Some code needs to vary between remote and local repos, these functions
|
{- User-visible description of a git repo by path or url -}
|
||||||
- help with that. -}
|
describe repo = if (local repo) then top repo else url repo
|
||||||
|
|
||||||
|
{- Some code needs to vary between remote and local repos, or bare and
|
||||||
|
- non-bare, these functions help with that. -}
|
||||||
local repo = case (repo) of
|
local repo = case (repo) of
|
||||||
LocalGitRepo {} -> True
|
LocalGitRepo {} -> True
|
||||||
RemoteGitRepo {} -> False
|
RemoteGitRepo {} -> False
|
||||||
|
@ -80,8 +78,16 @@ remote repo = not $ local repo
|
||||||
assertlocal repo action =
|
assertlocal repo action =
|
||||||
if (local repo)
|
if (local repo)
|
||||||
then action
|
then action
|
||||||
else error $ "acting on remote git repo " ++ (url repo) ++
|
else error $ "acting on remote git repo " ++ (describe repo) ++
|
||||||
" not supported"
|
" not supported"
|
||||||
|
bare :: GitRepo -> Bool
|
||||||
|
bare repo =
|
||||||
|
if (member b (config repo))
|
||||||
|
then ("true" == fromJust (Map.lookup b (config repo)))
|
||||||
|
else error $ "it is not known if git repo " ++ (describe repo) ++
|
||||||
|
" is a bare repository; config not read"
|
||||||
|
where
|
||||||
|
b = "core.bare"
|
||||||
|
|
||||||
{- Path to a repository's gitattributes file. -}
|
{- Path to a repository's gitattributes file. -}
|
||||||
gitAttributes :: GitRepo -> String
|
gitAttributes :: GitRepo -> String
|
||||||
|
@ -130,7 +136,11 @@ gitRm repo file = runGit repo ["rm", file]
|
||||||
gitCommandLine :: GitRepo -> [String] -> [String]
|
gitCommandLine :: GitRepo -> [String] -> [String]
|
||||||
gitCommandLine repo params = assertlocal repo $
|
gitCommandLine repo params = assertlocal repo $
|
||||||
-- force use of specified repo via --git-dir and --work-tree
|
-- force use of specified repo via --git-dir and --work-tree
|
||||||
["--git-dir="++(gitDir repo), "--work-tree="++(top repo)] ++ params
|
-- gitDir cannot be used for --git-dir because the config may
|
||||||
|
-- not have been read (and gitConfigRead relies on this function).
|
||||||
|
-- So this relies on git doing the right thing when told that
|
||||||
|
-- --git-dir is the top of a work tree.
|
||||||
|
["--git-dir="++(top repo), "--work-tree="++(top repo)] ++ params
|
||||||
|
|
||||||
{- Runs git in the specified repo. -}
|
{- Runs git in the specified repo. -}
|
||||||
runGit :: GitRepo -> [String] -> IO ()
|
runGit :: GitRepo -> [String] -> IO ()
|
||||||
|
@ -175,8 +185,8 @@ gitConfigRemotes repo = mapM construct remotes
|
||||||
isremote k = (startswith "remote." k) && (endswith ".url" k)
|
isremote k = (startswith "remote." k) && (endswith ".url" k)
|
||||||
construct r =
|
construct r =
|
||||||
if (isURI r)
|
if (isURI r)
|
||||||
then gitRepoFromUrl r
|
then gitRepoFromUrl r False
|
||||||
else gitRepoFromPath r
|
else gitRepoFromPath r False
|
||||||
|
|
||||||
{- Finds the current git repository, which may be in a parent directory. -}
|
{- Finds the current git repository, which may be in a parent directory. -}
|
||||||
gitRepoFromCwd :: IO GitRepo
|
gitRepoFromCwd :: IO GitRepo
|
||||||
|
@ -184,7 +194,7 @@ gitRepoFromCwd = do
|
||||||
cwd <- getCurrentDirectory
|
cwd <- getCurrentDirectory
|
||||||
top <- seekUp cwd isRepoTop
|
top <- seekUp cwd isRepoTop
|
||||||
case top of
|
case top of
|
||||||
(Just dir) -> gitRepoFromPath dir
|
(Just dir) -> gitRepoFromPath dir True
|
||||||
Nothing -> error "Not in a git repository."
|
Nothing -> error "Not in a git repository."
|
||||||
|
|
||||||
seekUp :: String -> (String -> IO Bool) -> IO (Maybe String)
|
seekUp :: String -> (String -> IO Bool) -> IO (Maybe String)
|
||||||
|
@ -200,11 +210,10 @@ isRepoTop dir = do
|
||||||
r <- isGitRepo dir
|
r <- isGitRepo dir
|
||||||
b <- isBareRepo dir
|
b <- isBareRepo dir
|
||||||
return (r || b)
|
return (r || b)
|
||||||
|
where
|
||||||
isGitRepo dir = gitSignature dir ".git" ".git/config"
|
isGitRepo dir = gitSignature dir ".git" ".git/config"
|
||||||
isBareRepo dir = gitSignature dir "objects" "config"
|
isBareRepo dir = gitSignature dir "objects" "config"
|
||||||
|
gitSignature dir subdir file = do
|
||||||
gitSignature dir subdir file = do
|
s <- (doesDirectoryExist (dir ++ "/" ++ subdir))
|
||||||
s <- (doesDirectoryExist (dir ++ "/" ++ subdir))
|
f <- (doesFileExist (dir ++ "/" ++ file))
|
||||||
f <- (doesFileExist (dir ++ "/" ++ file))
|
return (s && f)
|
||||||
return (s && f)
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue