1
0
Fork 0
mirror of https://code.naskya.net/repos/ndqEd synced 2025-01-11 07:56:48 +09:00
vervis/src/Data/Git/Local.hs

109 lines
3.3 KiB
Haskell

{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- ♡ Copying is an act of love. Please copy, reuse and share.
-
- The author(s) have dedicated all copyright and related and neighboring
- rights to this software to the public domain worldwide. This software is
- distributed without any warranty.
-
- You should have received a copy of the CC0 Public Domain Dedication along
- with this software. If not, see
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Data.Git.Local
( -- * Initialize repo
createRepo
-- * View repo content
, EntObjType (..)
, TreeRows
, PathView (..)
, viewPath
)
where
import Prelude
import Control.Monad (when)
import Data.Byteable (toBytes)
import Data.Git
import Data.Git.Harder
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8With)
import Data.Text.Encoding.Error (lenientDecode)
import System.Directory.Tree
import qualified Data.ByteString as B (ByteString, writeFile)
import qualified Data.ByteString.Lazy as BL (ByteString)
initialRepoTree :: FileName -> DirTree B.ByteString
initialRepoTree repo =
Dir repo
[ Dir "branches" []
, File "config"
"[core]\n\
\ repositoryformatversion = 0\n\
\ filemode = true\n\
\ bare = true"
, File "description"
"Unnamed repository; edit this file to name the repository."
, File "HEAD" "ref: refs/heads/master"
, Dir "hooks" []
, Dir "info"
[ File "exclude" ""
]
, Dir "objects"
[ Dir "info" []
, Dir "pack" []
]
, Dir "refs"
[ Dir "heads" []
, Dir "tags" []
]
]
-- | initialize a new bare repository at a specific location.
--
-- Currently in the @hit@ package, i.e. version 0.6.3, the initRepo function
-- creates a directory which the git executable doesn't recognize as a git
-- repository. The version here creates a properly initialized repo.
createRepo
:: FilePath
-- ^ Parent directory which already exists
-> String
-- ^ Name of new repo, i.e. new directory to create under the parent
-> IO ()
createRepo path name = do
let tree = path :/ initialRepoTree name
result <- writeDirectoryWith B.writeFile tree
let errs = failures $ dirTree result
when (not . null $ errs) $ error $ show errs
data EntObjType = EntObjBlob | EntObjTree
type TreeRows = [(ModePerm, ObjId, Text, EntObjType)]
data PathView
= RootView TreeRows
| TreeView Text ObjId TreeRows
| BlobView Text ObjId BL.ByteString
viewPath :: Git -> Tree -> EntPath -> IO PathView
viewPath git root path = do
let toEnt False = EntObjBlob
toEnt True = EntObjTree
toText = decodeUtf8With lenientDecode . toBytes
adapt (perm, oid, name, isTree) =
(perm, oid, toText name, toEnt isTree)
mkRows t = map adapt <$> viewTree git t
mno <- resolveTreePath git root path
case mno of
Nothing -> RootView <$> mkRows root
Just (name, oid) -> do
let nameT = toText name
target <- getEntryObject_ git oid
case target of
Left blob -> return $ BlobView nameT oid (blobGetContent blob)
Right tree -> TreeView nameT oid <$> mkRows tree