2011-12-14 19:30:14 +00:00
|
|
|
{- git SHA stuff
|
|
|
|
-
|
2020-01-07 15:35:17 +00:00
|
|
|
- Copyright 2011,2020 Joey Hess <id@joeyh.name>
|
2011-12-14 19:30:14 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2011-12-14 19:30:14 +00:00
|
|
|
-}
|
|
|
|
|
2020-04-06 21:14:49 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
2011-12-14 19:30:14 +00:00
|
|
|
module Git.Sha where
|
|
|
|
|
|
|
|
import Common
|
|
|
|
import Git.Types
|
|
|
|
|
2020-04-06 21:14:49 +00:00
|
|
|
import qualified Data.ByteString as S
|
|
|
|
import Data.Char
|
|
|
|
|
2011-12-15 19:57:47 +00:00
|
|
|
{- Runs an action that causes a git subcommand to emit a Sha, and strips
|
2012-12-13 04:45:27 +00:00
|
|
|
- any trailing newline, returning the sha. -}
|
2020-04-06 21:14:49 +00:00
|
|
|
getSha :: String -> IO S.ByteString -> IO Sha
|
2011-12-15 19:57:47 +00:00
|
|
|
getSha subcommand a = maybe bad return =<< extractSha <$> a
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
2023-04-10 17:38:14 +00:00
|
|
|
bad = giveup $ "failed to read sha from git " ++ subcommand
|
2011-12-15 19:57:47 +00:00
|
|
|
|
2020-04-06 21:14:49 +00:00
|
|
|
{- Extracts the Sha from a ByteString.
|
|
|
|
-
|
|
|
|
- There can be a trailing newline after it, but nothing else.
|
|
|
|
-}
|
|
|
|
extractSha :: S.ByteString -> Maybe Sha
|
2011-12-15 19:57:47 +00:00
|
|
|
extractSha s
|
2020-01-07 15:35:17 +00:00
|
|
|
| len `elem` shaSizes = val s
|
2020-04-06 21:14:49 +00:00
|
|
|
| len - 1 `elem` shaSizes && S.length s' == len - 1 = val s'
|
2011-12-15 19:57:47 +00:00
|
|
|
| otherwise = Nothing
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
2020-04-06 21:14:49 +00:00
|
|
|
len = S.length s
|
|
|
|
s' = firstLine' s
|
2012-12-13 04:24:19 +00:00
|
|
|
val v
|
2020-04-06 21:14:49 +00:00
|
|
|
| S.all validinsha v = Just $ Ref v
|
2012-12-13 04:24:19 +00:00
|
|
|
| otherwise = Nothing
|
2020-04-06 21:14:49 +00:00
|
|
|
validinsha w = or
|
|
|
|
[ w >= 48 && w <= 57 -- 0-9
|
|
|
|
, w >= 97 && w <= 102 -- a-f
|
|
|
|
, w >= 65 && w <= 70 -- A-F
|
|
|
|
]
|
2011-12-14 19:30:14 +00:00
|
|
|
|
2020-01-07 15:35:17 +00:00
|
|
|
{- Sizes of git shas. -}
|
|
|
|
shaSizes :: [Int]
|
|
|
|
shaSizes =
|
|
|
|
[ 40 -- sha1 (must come first)
|
|
|
|
, 64 -- sha256
|
|
|
|
]
|
2012-01-06 21:24:03 +00:00
|
|
|
|
2020-01-07 15:35:17 +00:00
|
|
|
{- Git plumbing often uses a all 0 sha to represent things like a
|
|
|
|
- deleted file. -}
|
|
|
|
nullShas :: [Sha]
|
2020-04-06 21:14:49 +00:00
|
|
|
nullShas = map (\n -> Ref (S.replicate n zero)) shaSizes
|
|
|
|
where
|
|
|
|
zero = fromIntegral (ord '0')
|
2014-02-16 21:39:54 +00:00
|
|
|
|
2020-01-07 15:35:17 +00:00
|
|
|
{- Sha to provide to git plumbing when deleting a file.
|
|
|
|
-
|
|
|
|
- It's ok to provide a sha1; git versions that use sha256 will map the
|
|
|
|
- sha1 to the sha256, or probably just treat all null sha1 specially
|
|
|
|
- the same as all null sha256. -}
|
|
|
|
deleteSha :: Sha
|
|
|
|
deleteSha = Prelude.head nullShas
|
|
|
|
|
|
|
|
{- Git's magic empty tree.
|
|
|
|
-
|
|
|
|
- It's ok to provide the sha1 of this to git to refer to an empty tree;
|
|
|
|
- git versions that use sha256 will map the sha1 to the sha256.
|
|
|
|
-}
|
2014-02-16 21:39:54 +00:00
|
|
|
emptyTree :: Ref
|
|
|
|
emptyTree = Ref "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|