packages feed

git-phoenix-0.0.1: src/Data/Git/Phoenix/Sha.hs

module Data.Git.Phoenix.Sha
  ( ComHash
  , hexToBin
  , shaToPath
  , binSha2Path
  , binSha2Str
  , parseSha1
  , showDigest
  , sha1
  , gitPath2Bs
  , cutGitPath
  ) where

import Crypto.Hash.SHA1 (hashlazy)
import Data.Binary qualified as B
import Data.ByteArray.Encoding (Base(Base16), convertFromBase, convertToBase)
import Data.ByteString.Char8 qualified as C
import Data.ByteString.Lazy.Char8 qualified as L8
import Data.Char (isHexDigit)
import Data.Git.Phoenix.Object
import Data.List.Extra qualified as L
import Relude

type ComHash = ByteString

sha1 :: LByteString -> ByteString
sha1 = hashlazy

showDigest :: ByteString -> String
showDigest = C.unpack . convertToBase Base16

parseSha1 :: String -> Either String ComHash
parseSha1
  h | length (filter isHexDigit h) == 40 =
      fmap (B.decode . toLazy) $ convertFromBase Base16 (C.pack h)
    | otherwise = Left $ "Failed to parse SHA1: " <> h

fromRightEr :: Either String a -> a
fromRightEr = \case
  Right a -> a
  Left e -> error $ toText e

hexToBin :: LByteString -> LByteString
hexToBin = toLazy . fromRightEr . convertFromBase Base16 . toStrict

shaToPath :: String -> GitPath a
shaToPath = \case
  a:b:r -> GitPath $ a:b:'/':r
  o -> GitPath o

binSha2Path :: LByteString -> GitPath a
binSha2Path = shaToPath . binSha2Str

binSha2Str :: LByteString -> String
binSha2Str = C.unpack . convertToBase Base16 . toStrict

gitPath2Bs :: GitPath a -> LByteString
gitPath2Bs (GitPath fp) =
  case fp of
    a:b:'/':r -> hexToBin . L8.pack $ a:b:r
    _ -> error . toText $ "Bad GitPath: " <> fp

cutGitPath :: FilePath -> Maybe LByteString
cutGitPath fp =
  case L.takeEnd 41 fp of
    a:b:'/':r -> Just . hexToBin . L8.pack $ a:b:r
    _ -> Nothing