Re-implement Browse API to avoid loading entire codebase root (#3054)

Swap Browse API to use V2 branches.
This commit is contained in:
Chris Penner 2022-04-26 09:41:31 -06:00 committed by GitHub
parent 3bfb412a4d
commit d79e396c44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 400 additions and 137 deletions

View File

@ -6,6 +6,7 @@ module U.Codebase.Sqlite.Operations
expectRootCausal,
saveBranch,
loadCausalBranchByCausalHash,
expectCausalBranchByCausalHash,
-- * terms
saveTermComponent,
@ -857,7 +858,7 @@ s2cBranch (S.Branch.Full.Branch tms tps patches children) =
boId <- Q.expectBranchObjectIdByCausalHashId chId
expectBranch boId
saveRootBranch :: C.Branch.Causal Transaction -> Transaction (Db.BranchObjectId, Db.CausalHashId)
saveRootBranch :: C.Branch.CausalBranch Transaction -> Transaction (Db.BranchObjectId, Db.CausalHashId)
saveRootBranch c = do
when debug $ traceM $ "Operations.saveRootBranch " ++ show (C.causalHash c)
(boId, chId) <- saveBranch c
@ -903,7 +904,7 @@ saveRootBranch c = do
-- References, but also values
-- Shallow - Hash? representation of the database relationships
saveBranch :: C.Branch.Causal Transaction -> Transaction (Db.BranchObjectId, Db.CausalHashId)
saveBranch :: C.Branch.CausalBranch Transaction -> Transaction (Db.BranchObjectId, Db.CausalHashId)
saveBranch (C.Causal hc he parents me) = do
when debug $ traceM $ "\nOperations.saveBranch \n hc = " ++ show hc ++ ",\n he = " ++ show he ++ ",\n parents = " ++ show (Map.keys parents)
@ -961,25 +962,30 @@ saveBranchObject id@(Db.unBranchHashId -> hashId) li lBranch = do
oId <- Q.saveObject hashId OT.Namespace bytes
pure $ Db.BranchObjectId oId
expectRootCausal :: Transaction (C.Branch.Causal Transaction)
expectRootCausal = Q.expectNamespaceRoot >>= expectCausalByCausalHashId
expectRootCausal :: Transaction (C.Branch.CausalBranch Transaction)
expectRootCausal = Q.expectNamespaceRoot >>= expectCausalBranchByCausalHashId
loadCausalBranchByCausalHash :: CausalHash -> Transaction (Maybe (C.Branch.Causal Transaction))
loadCausalBranchByCausalHash :: CausalHash -> Transaction (Maybe (C.Branch.CausalBranch Transaction))
loadCausalBranchByCausalHash hc = do
Q.loadCausalHashIdByCausalHash hc >>= \case
Just chId -> Just <$> expectCausalByCausalHashId chId
Just chId -> Just <$> expectCausalBranchByCausalHashId chId
Nothing -> pure Nothing
expectCausalByCausalHashId :: Db.CausalHashId -> Transaction (C.Branch.Causal Transaction)
expectCausalByCausalHashId id = do
expectCausalBranchByCausalHashId :: Db.CausalHashId -> Transaction (C.Branch.CausalBranch Transaction)
expectCausalBranchByCausalHashId id = do
hc <- Q.expectCausalHash id
hb <- expectValueHashByCausalHashId id
parentHashIds <- Q.loadCausalParents id
loadParents <- for parentHashIds \hId -> do
h <- Q.expectCausalHash hId
pure (h, expectCausalByCausalHashId hId)
pure (h, expectCausalBranchByCausalHashId hId)
pure $ C.Causal hc hb (Map.fromList loadParents) (expectBranchByCausalHashId id)
expectCausalBranchByCausalHash :: CausalHash -> Transaction (C.Branch.CausalBranch Transaction)
expectCausalBranchByCausalHash hash = do
chId <- Q.expectCausalHashIdByCausalHash hash
expectCausalBranchByCausalHashId chId
expectBranchByCausalHashId :: Db.CausalHashId -> Transaction (C.Branch.Branch Transaction)
expectBranchByCausalHashId id = do
boId <- Q.expectBranchObjectIdByCausalHashId id

View File

@ -66,8 +66,10 @@ module U.Codebase.Sqlite.Queries
saveCausal,
isCausalHash,
loadCausalHashIdByCausalHash,
expectCausalHashIdByCausalHash,
expectCausalValueHashId,
loadCausalByCausalHash,
expectCausalByCausalHash,
loadBranchObjectIdByCausalHashId,
expectBranchObjectIdByCausalHashId,
@ -238,12 +240,23 @@ loadCausalHashIdByCausalHash ch = runMaybeT do
hId <- MaybeT $ loadHashIdByHash (unCausalHash ch)
Alternative.whenM (lift (isCausalHash hId)) (CausalHashId hId)
expectCausalHashIdByCausalHash :: CausalHash -> Transaction CausalHashId
expectCausalHashIdByCausalHash ch = do
hId <- expectHashIdByHash (unCausalHash ch)
pure (CausalHashId hId)
loadCausalByCausalHash :: CausalHash -> Transaction (Maybe (CausalHashId, BranchHashId))
loadCausalByCausalHash ch = runMaybeT do
hId <- MaybeT $ loadHashIdByHash (unCausalHash ch)
bhId <- MaybeT $ loadCausalValueHashId hId
pure (CausalHashId hId, bhId)
expectCausalByCausalHash :: CausalHash -> Transaction (CausalHashId, BranchHashId)
expectCausalByCausalHash ch = do
hId <- expectCausalHashIdByCausalHash ch
bhId <- expectCausalValueHashId hId
pure (hId, bhId)
expectHashIdByHash :: Hash -> Transaction HashId
expectHashIdByHash = expectHashId . Hash.toBase32Hex

View File

@ -1,15 +1,31 @@
module U.Codebase.Branch where
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
import Data.Map (Map)
module U.Codebase.Branch
( Branch (..),
CausalBranch,
Patch (..),
MetadataType,
MetadataValue,
MdValues (..),
NameSegment (..),
CausalHash,
childAt,
hoist,
hoistCausalBranch,
)
where
import Control.Lens (AsEmpty (..), nearly)
import qualified Data.Map as Map
import Data.Set (Set)
import Data.Text (Text)
import qualified U.Codebase.Causal as C
import U.Codebase.Causal (Causal)
import qualified U.Codebase.Causal as Causal
import U.Codebase.HashTags (BranchHash, CausalHash, PatchHash)
import U.Codebase.Reference (Reference)
import U.Codebase.Referent (Referent)
import U.Codebase.TermEdit (TermEdit)
import U.Codebase.TypeEdit (TypeEdit)
import Unison.Prelude
newtype NameSegment = NameSegment {unNameSegment :: Text} deriving (Eq, Ord, Show)
@ -19,16 +35,23 @@ type MetadataValue = Reference
data MdValues = MdValues (Map MetadataValue MetadataType) deriving (Eq, Ord, Show)
type Causal m = C.Causal m CausalHash BranchHash (Branch m)
type CausalBranch m = Causal m CausalHash BranchHash (Branch m)
-- | V2.Branch is like V1.Branch0; I would rename it, at least temporarily, but too hard.
-- | A re-imagining of Unison.Codebase.Branch which is less eager in what it loads,
-- which can often speed up load times and keep fewer things in memory.
data Branch m = Branch
{ terms :: Map NameSegment (Map Referent (m MdValues)),
types :: Map NameSegment (Map Reference (m MdValues)),
patches :: Map NameSegment (PatchHash, m Patch),
children :: Map NameSegment (Causal m)
children :: Map NameSegment (CausalBranch m)
}
instance AsEmpty (Branch m) where
_Empty =
nearly
(Branch mempty mempty mempty mempty)
(\(Branch terms types patches children) -> null terms && null types && null patches && null children)
data Patch = Patch
{ termEdits :: Map Referent (Set TermEdit),
typeEdits :: Map Reference (Set TypeEdit)
@ -43,3 +66,21 @@ instance Show (Branch m) where
++ show (fmap fst (patches b))
++ ", children = "
++ show (Map.keys (children b))
childAt :: NameSegment -> Branch m -> Maybe (CausalBranch m)
childAt ns (Branch {children}) = Map.lookup ns children
hoist :: Functor n => (forall x. m x -> n x) -> Branch m -> Branch n
hoist f Branch {..} =
Branch
{ terms = (fmap . fmap) f terms,
types = (fmap . fmap) f types,
patches = (fmap . fmap) f patches,
children = fmap (fmap (hoist f) . Causal.hoist f) children
}
hoistCausalBranch :: Functor n => (forall x. m x -> n x) -> CausalBranch m -> CausalBranch n
hoistCausalBranch f cb =
cb
& Causal.hoist f
& fmap (hoist f)

View File

@ -1,9 +1,14 @@
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
module U.Codebase.Causal where
module U.Codebase.Causal
( Causal (..),
hoist,
)
where
import Data.Map (Map)
import Unison.Prelude
data Causal m hc he e = Causal
{ causalHash :: hc,
@ -11,3 +16,12 @@ data Causal m hc he e = Causal
parents :: Map hc (m (Causal m hc he e)),
value :: m e
}
deriving (Functor)
hoist :: Functor n => (forall x. m x -> n x) -> Causal m hc he e -> Causal n hc he e
hoist f (Causal {..}) =
Causal
{ parents = parents & fmap f & (fmap . fmap) (hoist f),
value = f value,
..
}

View File

@ -6,6 +6,7 @@ module U.Util.Hash
fromBase32Hex,
fromByteString,
toBase32Hex,
toBase32HexText,
toByteString,
)
where

View File

@ -7,6 +7,7 @@ module Unison.Codebase
unsafeGetTermWithType,
getTermComponentWithTypes,
getTypeOfTerm,
getDeclType,
unsafeGetTypeOfTermById,
isTerm,
putTerm,
@ -35,6 +36,9 @@ module Unison.Codebase
branchHashesByPrefix,
lca,
beforeImpl,
shallowBranchAtPath,
getShallowBranchForHash,
getShallowRootBranch,
-- * Root branch
getRootBranch,
@ -99,6 +103,9 @@ import Control.Monad.Trans.Except (throwE)
import Data.List as List
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified U.Codebase.Branch as V2
import qualified U.Codebase.Branch as V2Branch
import qualified U.Codebase.Causal as V2Causal
import U.Util.Timing (time)
import qualified Unison.Builtin as Builtin
import qualified Unison.Builtin.Terms as Builtin
@ -110,6 +117,9 @@ import Unison.Codebase.Editor.Git (withStatus)
import qualified Unison.Codebase.Editor.Git as Git
import Unison.Codebase.Editor.RemoteRepo (ReadRemoteNamespace)
import qualified Unison.Codebase.GitError as GitError
import Unison.Codebase.Path
import qualified Unison.Codebase.Path as Path
import qualified Unison.Codebase.SqliteCodebase.Conversions as Cv
import Unison.Codebase.SyncMode (SyncMode)
import Unison.Codebase.Type
( Codebase (..),
@ -140,6 +150,24 @@ import qualified Unison.Util.Relation as Rel
import Unison.Var (Var)
import qualified Unison.WatchKind as WK
-- | Get the shallow representation of the root branches without loading the children or
-- history.
getShallowRootBranch :: Monad m => Codebase m v a -> m (V2.CausalBranch m)
getShallowRootBranch codebase = do
hash <- getRootBranchHash codebase
getShallowBranchForHash codebase hash
-- | Recursively descend into shallow branches following the given path.
shallowBranchAtPath :: Monad m => Path -> V2Branch.CausalBranch m -> m (Maybe (V2Branch.CausalBranch m))
shallowBranchAtPath path causal = do
case path of
Path.Empty -> pure (Just causal)
(ns Path.:< p) -> do
b <- V2Causal.value causal
case (V2Branch.childAt (Cv.namesegment1to2 ns) b) of
Nothing -> pure Nothing
Just childCausal -> shallowBranchAtPath p childCausal
-- | Get a branch from the codebase.
getBranchForHash :: Monad m => Codebase m v a -> Branch.Hash -> m (Maybe (Branch m))
getBranchForHash codebase h =

View File

@ -9,7 +9,7 @@ module Unison.Codebase.Branch
Branch (..),
UnwrappedBranch,
Branch0 (..),
Raw (..),
Raw,
Star,
Hash,
EditHash,
@ -88,7 +88,7 @@ import qualified Data.Map as Map
import qualified Data.Semialign as Align
import qualified Data.Set as Set
import Data.These (These (..))
import Unison.Codebase.Branch.Raw (Raw (Raw))
import Unison.Codebase.Branch.Raw (Raw)
import Unison.Codebase.Branch.Type
( Branch (..),
Branch0 (..),
@ -617,13 +617,13 @@ addTypeName r new md =
deleteTermName :: Referent -> NameSegment -> Branch0 m -> Branch0 m
deleteTermName r n b
| Star3.memberD1 (r, n) (view terms b) =
over terms (Star3.deletePrimaryD1 (r, n)) b
over terms (Star3.deletePrimaryD1 (r, n)) b
deleteTermName _ _ b = b
deleteTypeName :: TypeReference -> NameSegment -> Branch0 m -> Branch0 m
deleteTypeName r n b
| Star3.memberD1 (r, n) (view types b) =
over types (Star3.deletePrimaryD1 (r, n)) b
over types (Star3.deletePrimaryD1 (r, n)) b
deleteTypeName _ _ b = b
lca :: Monad m => Branch m -> Branch m -> m (Maybe (Branch m))

View File

@ -1,7 +1,9 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ViewPatterns #-}
module Unison.Codebase.Path
@ -11,6 +13,8 @@ module Unison.Codebase.Path
Relative (..),
Resolve (..),
pattern Empty,
pattern (Lens.:<),
pattern (Lens.:>),
singleton,
Unison.Codebase.Path.uncons,
empty,
@ -67,7 +71,7 @@ module Unison.Codebase.Path
)
where
import Control.Lens hiding (Empty, cons, snoc, unsnoc)
import Control.Lens hiding (cons, snoc, unsnoc, pattern Empty)
import qualified Control.Lens as Lens
import qualified Data.Foldable as Foldable
import Data.List.Extra (dropPrefix)
@ -270,6 +274,12 @@ toText' = \case
Path' (Left (Absolute path)) -> Text.cons '.' (toText path)
Path' (Right (Relative path)) -> toText path
{-# COMPLETE Empty, (:<) #-}
{-# COMPLETE Empty, (:>) #-}
deriving anyclass instance AsEmpty Path
instance Cons Path Path NameSegment NameSegment where
_Cons = prism (uncurry cons) uncons
where

View File

@ -2,7 +2,6 @@ module Unison.Codebase.ShortBranchHash
( toString,
toHash,
fromHash,
fullFromHash,
fromText,
ShortBranchHash (..),
)
@ -26,16 +25,13 @@ fromHash :: Coercible h Hash.Hash => Int -> h -> ShortBranchHash
fromHash len =
ShortBranchHash . Text.take len . Hash.base32Hex . coerce
fullFromHash :: Coercible h Hash.Hash => h -> ShortBranchHash
fullFromHash = ShortBranchHash . Hash.base32Hex . coerce
-- abc -> SBH abc
-- #abc -> SBH abc
fromText :: Text -> Maybe ShortBranchHash
fromText (Text.dropWhile (== '#') -> t)
| Text.all (`Set.member` Hash.validBase32HexChars) t =
Just $
ShortBranchHash t
Just $
ShortBranchHash t
fromText _ = Nothing
instance Show ShortBranchHash where

View File

@ -27,6 +27,7 @@ import qualified System.Console.ANSI as ANSI
import System.FilePath ((</>))
import qualified System.FilePath as FilePath
import qualified System.FilePath.Posix as FilePath.Posix
import qualified U.Codebase.Branch as V2Branch
import U.Codebase.HashTags (CausalHash (CausalHash))
import qualified U.Codebase.Reference as C.Reference
import qualified U.Codebase.Sqlite.Operations as Ops
@ -247,6 +248,16 @@ sqliteCodebase debugName root localOrRemote action = do
putTypeDeclaration id decl =
Sqlite.runTransaction conn (CodebaseOps.putTypeDeclaration termBuffer declBuffer id decl)
getRootBranchHash :: MonadIO m => m V2Branch.CausalHash
getRootBranchHash = do
Sqlite.runReadOnlyTransaction conn \run ->
run Ops.expectRootCausalHash
getShallowBranchForHash :: MonadIO m => V2Branch.CausalHash -> m (V2Branch.CausalBranch m)
getShallowBranchForHash bh =
Sqlite.runReadOnlyTransaction conn \run -> do
V2Branch.hoistCausalBranch run <$> run (Ops.expectCausalBranchByCausalHash bh)
getRootBranch :: TVar (Maybe (Sqlite.DataVersion, Branch Sqlite.Transaction)) -> m (Branch m)
getRootBranch rootBranchCache =
Sqlite.runReadOnlyTransaction conn \run ->
@ -433,47 +444,50 @@ sqliteCodebase debugName root localOrRemote action = do
Sqlite.runTransaction conn (CodebaseOps.sqlLca h1 h2)
let codebase =
C.Codebase
(Cache.applyDefined termCache getTerm)
(Cache.applyDefined typeOfTermCache getTypeOfTermImpl)
(Cache.applyDefined declCache getTypeDeclaration)
putTerm
putTypeDeclaration
-- _getTermComponent
getTermComponentWithTypes
getDeclComponent
getCycleLength
(getRootBranch rootBranchCache)
getRootBranchExists
(putRootBranch rootBranchCache)
(rootBranchUpdates rootBranchCache)
getBranchForHash
putBranch
isCausalHash
getPatch
putPatch
patchExists
dependentsImpl
dependentsOfComponentImpl
syncFromDirectory
syncToDirectory
viewRemoteBranch'
(\r opts action -> pushGitBranch conn r opts action)
watches
getWatch
putWatch
clearWatches
getReflog
appendReflog
termsOfTypeImpl
termsMentioningTypeImpl
hashLength
termReferencesByPrefix
declReferencesByPrefix
referentsByPrefix
branchHashLength
branchHashesByPrefix
(Just sqlLca)
(Just \l r -> Sqlite.runTransaction conn $ fromJust <$> CodebaseOps.before l r)
{ getTerm = (Cache.applyDefined termCache getTerm),
getTypeOfTermImpl = (Cache.applyDefined typeOfTermCache getTypeOfTermImpl),
getTypeDeclaration = (Cache.applyDefined declCache getTypeDeclaration),
getDeclType = \r -> Sqlite.runReadOnlyTransaction conn \run -> run (getDeclType r),
putTerm = putTerm,
putTypeDeclaration = putTypeDeclaration,
getTermComponentWithTypes = getTermComponentWithTypes,
getDeclComponent = getDeclComponent,
getComponentLength = getCycleLength,
getRootBranch = (getRootBranch rootBranchCache),
getRootBranchHash = getRootBranchHash,
getRootBranchExists = getRootBranchExists,
putRootBranch = (putRootBranch rootBranchCache),
rootBranchUpdates = (rootBranchUpdates rootBranchCache),
getShallowBranchForHash = getShallowBranchForHash,
getBranchForHashImpl = getBranchForHash,
putBranch = putBranch,
branchExists = isCausalHash,
getPatch = getPatch,
putPatch = putPatch,
patchExists = patchExists,
dependentsImpl = dependentsImpl,
dependentsOfComponentImpl = dependentsOfComponentImpl,
syncFromDirectory = syncFromDirectory,
syncToDirectory = syncToDirectory,
viewRemoteBranch' = viewRemoteBranch',
pushGitBranch = (\r opts action -> pushGitBranch conn r opts action),
watches = watches,
getWatch = getWatch,
putWatch = putWatch,
clearWatches = clearWatches,
getReflog = getReflog,
appendReflog = appendReflog,
termsOfTypeImpl = termsOfTypeImpl,
termsMentioningTypeImpl = termsMentioningTypeImpl,
hashLength = hashLength,
termReferencesByPrefix = termReferencesByPrefix,
typeReferencesByPrefix = declReferencesByPrefix,
termReferentsByPrefix = referentsByPrefix,
branchHashLength = branchHashLength,
branchHashesByPrefix = branchHashesByPrefix,
lcaImpl = (Just sqlLca),
beforeImpl = (Just \l r -> Sqlite.runTransaction conn $ fromJust <$> CodebaseOps.before l r)
}
let finalizer :: MonadIO m => m ()
finalizer = do
decls <- readTVarIO declBuffer

View File

@ -410,10 +410,10 @@ type1to2' convertRef =
V1.Kind.Arrow i o -> V2.Kind.Arrow (convertKind i) (convertKind o)
-- | forces loading v1 branches even if they may not exist
causalbranch2to1 :: Monad m => (V2.Reference -> m CT.ConstructorType) -> V2.Branch.Causal m -> m (V1.Branch.Branch m)
causalbranch2to1 :: Monad m => (V2.Reference -> m CT.ConstructorType) -> V2.Branch.CausalBranch m -> m (V1.Branch.Branch m)
causalbranch2to1 lookupCT = fmap V1.Branch.Branch . causalbranch2to1' lookupCT
causalbranch2to1' :: Monad m => (V2.Reference -> m CT.ConstructorType) -> V2.Branch.Causal m -> m (V1.Branch.UnwrappedBranch m)
causalbranch2to1' :: Monad m => (V2.Reference -> m CT.ConstructorType) -> V2.Branch.CausalBranch m -> m (V1.Branch.UnwrappedBranch m)
causalbranch2to1' lookupCT (V2.Causal hc _he (Map.toList -> parents) me) = do
let currentHash = causalHash2to1 hc
case parents of
@ -428,7 +428,7 @@ causalbranch2to1' lookupCT (V2.Causal hc _he (Map.toList -> parents) me) = do
e <- me
V1.Causal.UnsafeMerge currentHash <$> branch2to1 lookupCT e <*> pure (Map.fromList tailsList)
causalbranch1to2 :: forall m. Monad m => V1.Branch.Branch m -> V2.Branch.Causal m
causalbranch1to2 :: forall m. Monad m => V1.Branch.Branch m -> V2.Branch.CausalBranch m
causalbranch1to2 (V1.Branch.Branch c) = causal1to2' hash1to2cb hash1to2c branch1to2 c
where
hash1to2cb :: V1.Branch.Hash -> (V2.CausalHash, V2.BranchHash)
@ -491,7 +491,7 @@ causalbranch1to2 (V1.Branch.Branch c) = causal1to2' hash1to2cb hash1to2c branch1
doPatches :: Map V1.NameSegment (V1.Branch.EditHash, m V1.Patch) -> Map V2.Branch.NameSegment (V2.PatchHash, m V2.Branch.Patch)
doPatches = Map.bimap namesegment1to2 (bimap edithash1to2 (fmap patch1to2))
doChildren :: Map V1.NameSegment (V1.Branch.Branch m) -> Map V2.Branch.NameSegment (V2.Branch.Causal m)
doChildren :: Map V1.NameSegment (V1.Branch.Branch m) -> Map V2.Branch.NameSegment (V2.Branch.CausalBranch m)
doChildren = Map.bimap namesegment1to2 causalbranch1to2
patch2to1 :: V2.Branch.Patch -> V1.Patch

View File

@ -12,6 +12,8 @@ module Unison.Codebase.Type
)
where
import qualified U.Codebase.Branch as V2
import qualified U.Codebase.Reference as V2
import Unison.Codebase.Branch (Branch)
import qualified Unison.Codebase.Branch as Branch
import qualified Unison.Codebase.Editor.Git as Git
@ -24,6 +26,7 @@ import Unison.Codebase.ShortBranchHash (ShortBranchHash)
import Unison.Codebase.SqliteCodebase.GitError (GitSqliteCodebaseError (..))
import Unison.Codebase.SyncMode (SyncMode)
import Unison.CodebasePath (CodebasePath)
import qualified Unison.ConstructorType as CT
import Unison.DataDeclaration (Decl)
import Unison.Hash (Hash)
import Unison.Prelude
@ -58,6 +61,8 @@ data Codebase m v a = Codebase
-- Note that it is possible to call 'putTypeDeclaration', then 'getTypeDeclaration', and receive @Nothing@, per the
-- semantics of 'putTypeDeclaration'.
getTypeDeclaration :: Reference.Id -> m (Maybe (Decl v a)),
-- | Get the type of a given decl.
getDeclType :: V2.Reference -> m CT.ConstructorType,
-- | Enqueue the put of a user-defined term (with its type) into the codebase, if it doesn't already exist. The
-- implementation may choose to delay the put until all of the term's (and its type's) references are stored as
-- well.
@ -69,6 +74,8 @@ data Codebase m v a = Codebase
getTermComponentWithTypes :: Hash -> m (Maybe [(Term v a, Type v a)]),
getDeclComponent :: Hash -> m (Maybe [Decl v a]),
getComponentLength :: Hash -> m (Maybe Reference.CycleSize),
-- | Get the root branch Hash.
getRootBranchHash :: m V2.CausalHash,
-- | Get the root branch.
getRootBranch :: m (Branch m),
-- | Get whether the root branch exists.
@ -76,6 +83,7 @@ data Codebase m v a = Codebase
-- | Like 'putBranch', but also adjusts the root branch pointer afterwards.
putRootBranch :: Branch m -> m (),
rootBranchUpdates :: m (IO (), IO (Set Branch.Hash)),
getShallowBranchForHash :: V2.CausalHash -> m (V2.CausalBranch m),
getBranchForHashImpl :: Branch.Hash -> m (Maybe (Branch m)),
-- | Put a branch into the codebase, which includes its children, its patches, and the branch itself, if they don't
-- already exist.

View File

@ -31,6 +31,7 @@ import System.Directory
getHomeDirectory,
)
import U.Codebase.Sqlite.DbId (SchemaVersion (SchemaVersion))
import qualified U.Util.Hash as Hash
import qualified U.Util.Monoid as Monoid
import qualified Unison.ABT as ABT
import qualified Unison.Auth.Types as Auth
@ -622,8 +623,8 @@ notifyUser dir o = case o of
CachedTests 0 _ -> pure . P.callout "😶" $ "No tests to run."
CachedTests n n'
| n == n' ->
pure $
P.lines [cache, "", displayTestResults True ppe oks fails]
pure $
P.lines [cache, "", displayTestResults True ppe oks fails]
CachedTests _n m ->
pure $
if m == 0
@ -632,7 +633,6 @@ notifyUser dir o = case o of
P.indentN 2 $
P.lines ["", cache, "", displayTestResults False ppe oks fails, "", ""]
where
NewlyComputed -> do
clearCurrentLine
pure $
@ -892,8 +892,9 @@ notifyUser dir o = case o of
ShallowBranchEntry ns _ count ->
( (P.syntaxToColor . prettyName . Name.fromSegment) ns <> "/",
case count of
1 -> P.lit "(1 definition)"
_n -> P.lit "(" <> P.shown count <> P.lit " definitions)"
Nothing -> "(namespace)"
Just 1 -> P.lit "(1 definition)"
Just n -> P.lit "(" <> P.shown n <> P.lit " definitions)"
)
ShallowPatchEntry ns ->
( (P.syntaxToColor . prettyName . Name.fromSegment) ns,
@ -1631,6 +1632,9 @@ prettyAbsolute = P.blue . P.shown
prettySBH :: IsString s => ShortBranchHash -> P.Pretty s
prettySBH hash = P.group $ "#" <> P.text (SBH.toText hash)
prettyCausalHash :: IsString s => Causal.RawHash x -> P.Pretty s
prettyCausalHash hash = P.group $ "#" <> P.text (Hash.toBase32HexText . Causal.unRawHash $ hash)
formatMissingStuff ::
(Show tm, Show typ) =>
[(HQ.HashQualified Name, tm)] ->
@ -2161,7 +2165,7 @@ showDiffNamespace ::
(Pretty, NumberedArgs)
showDiffNamespace _ _ _ _ diffOutput
| OBD.isEmpty diffOutput =
("The namespaces are identical.", mempty)
("The namespaces are identical.", mempty)
showDiffNamespace sn ppe oldPath newPath OBD.BranchDiffOutput {..} =
(P.sepNonEmpty "\n\n" p, toList args)
where

View File

@ -18,6 +18,7 @@ dependencies:
- aeson
- memory
- unison-util-relation
- unison-codebase
- unison-core1
- unison-prelude
- unison-parser-typechecker
@ -44,6 +45,7 @@ dependencies:
- utf8-string
- async
- regex-tdfa
- unison-util
ghc-options:
-Wall

View File

@ -10,13 +10,12 @@
module Unison.Server.Backend where
import Control.Error.Util (hush, (??))
import Control.Lens (over, (^.), _2)
import Control.Lens.Cons
import Control.Lens hiding ((??))
import Control.Monad.Except
( ExceptT (..),
throwError,
)
import Data.Bifunctor (bimap, first)
import Data.Bifunctor (first)
import Data.Containers.ListUtils (nubOrdOn)
import qualified Data.List as List
import Data.List.Extra (nubOrd)
@ -31,6 +30,9 @@ import qualified Lucid
import System.Directory
import System.FilePath
import qualified Text.FuzzyFind as FZF
import qualified U.Codebase.Branch as V2Branch
import qualified U.Codebase.Causal as V2Causal
import qualified U.Codebase.Referent as V2
import qualified Unison.ABT as ABT
import qualified Unison.Builtin as B
import qualified Unison.Builtin.Decls as Decls
@ -50,6 +52,7 @@ import Unison.Codebase.ShortBranchHash
( ShortBranchHash,
)
import qualified Unison.Codebase.ShortBranchHash as SBH
import qualified Unison.Codebase.SqliteCodebase.Conversions as Cv
import Unison.ConstructorReference (GConstructorReference (..))
import qualified Unison.ConstructorReference as ConstructorReference
import qualified Unison.DataDeclaration as DD
@ -65,7 +68,7 @@ import qualified Unison.Name as Name
import qualified Unison.NamePrinter as NP
import Unison.NameSegment (NameSegment (..))
import qualified Unison.NameSegment as NameSegment
import Unison.Names (Names)
import Unison.Names (Names (Names))
import qualified Unison.Names as Names
import Unison.NamesWithHistory (NamesWithHistory (..))
import qualified Unison.NamesWithHistory as NamesWithHistory
@ -103,6 +106,7 @@ import qualified Unison.Util.Monoid as Monoid
import Unison.Util.Pretty (Width)
import qualified Unison.Util.Pretty as Pretty
import qualified Unison.Util.Relation as R
import qualified Unison.Util.Set as Set
import qualified Unison.Util.Star3 as Star3
import qualified Unison.Util.SyntaxText as UST
import Unison.Var (Var)
@ -113,8 +117,9 @@ type SyntaxText = UST.SyntaxText' Reference
data ShallowListEntry v a
= ShallowTermEntry (TermEntry v a)
| ShallowTypeEntry TypeEntry
| -- The integer here represents the number of children
ShallowBranchEntry NameSegment ShortBranchHash Int
| -- The integer here represents the number of children.
-- it may be omitted depending on the context the query is run in.
ShallowBranchEntry NameSegment Branch.Hash (Maybe Int)
| ShallowPatchEntry NameSegment
deriving (Eq, Ord, Show, Generic)
@ -183,6 +188,32 @@ basicSuffixifiedNames hashLength root nameScope =
basicPrettyPrintNames :: Branch m -> NameScoping -> Names
basicPrettyPrintNames root = snd . basicNames' root
shallowPPE :: Monad m => Codebase m v a -> V2Branch.Branch m -> m PPE.PrettyPrintEnv
shallowPPE codebase b = do
hashLength <- Codebase.hashLength codebase
names <- shallowNames codebase b
pure $ PPE.suffixifiedPPE . PPE.fromNamesDecl hashLength $ NamesWithHistory names mempty
-- | A 'Names' which only includes mappings for things _directly_ accessible from the branch.
--
-- I.e. names in nested children are omitted.
-- This should probably live elsewhere, but the package dependency graph makes it hard to find
-- a good place.
shallowNames :: forall m v a. Monad m => Codebase m v a -> V2Branch.Branch m -> m Names
shallowNames codebase b = do
newTerms <-
V2Branch.terms b
& Map.mapKeys (Name.fromSegment . Cv.namesegment2to1)
& fmap Map.keysSet
& traverse . Set.traverse %%~ Cv.referent2to1 (Codebase.getDeclType codebase)
let newTypes =
V2Branch.types b
& Map.mapKeys (Name.fromSegment . Cv.namesegment2to1)
& fmap Map.keysSet
& traverse . Set.traverse %~ Cv.reference2to1
pure (Names (R.fromMultimap newTerms) (R.fromMultimap newTypes))
basicParseNames :: Branch m -> NameScoping -> Names
basicParseNames root = fst . basicNames' root
@ -277,7 +308,7 @@ findShallow codebase path' = do
let mayb = Branch.getAt path root
case mayb of
Nothing -> pure []
Just b -> findShallowInBranch codebase b
Just b -> lsBranch codebase b
findShallowReadmeInBranchAndRender ::
Width ->
@ -321,16 +352,12 @@ isDoc' typeOfTerm = do
termListEntry ::
Monad m =>
Codebase m Symbol Ann ->
Branch0 m ->
Bool ->
Referent ->
HQ'.HQSegment ->
m (TermEntry Symbol Ann)
termListEntry codebase b0 r n = do
termListEntry codebase isTest r n = do
ot <- loadReferentType codebase r
-- A term is a test if it has a link of type `IsTest`.
let isTest = Metadata.hasMetadataWithType' r Decls.isTestRef $ Branch.deepTermMetadata b0
let tag =
if (isDoc' ot)
then Just Doc
@ -341,6 +368,20 @@ termListEntry codebase b0 r n = do
pure $ TermEntry r n ot tag
checkIsTestForBranch :: Branch0 m -> Referent -> Bool
checkIsTestForBranch b0 r =
Metadata.hasMetadataWithType' r Decls.isTestRef $ Branch.deepTermMetadata b0
checkIsTestForV2Branch :: Monad m => V2Branch.Branch m -> V2.Referent -> m Bool
checkIsTestForV2Branch b r = do
-- TODO: Should V2Branch use some sort of relation here?
or <$> for (toList $ V2Branch.terms b) \metaMap -> do
case Map.lookup r metaMap of
Nothing -> pure False
Just getMdValues -> do
V2Branch.MdValues mdValues <- getMdValues
pure $ elem (Cv.reference1to2 Decls.isTestRef) mdValues
typeListEntry ::
Monad m =>
Var v =>
@ -408,12 +449,15 @@ typeEntryToNamedType (TypeEntry r name tag) =
typeTag = tag
}
findShallowInBranch ::
-- | Find all definitions and children reachable from the given branch.
-- Note: this differs from 'lsShallowBranch' in that it takes a fully loaded 'Branch' object,
-- and thus can include definition counts for child namespaces.
lsBranch ::
Monad m =>
Codebase m Symbol Ann ->
Branch m ->
m [ShallowListEntry Symbol Ann]
findShallowInBranch codebase b = do
lsBranch codebase b = do
hashLength <- Codebase.hashLength codebase
let hqTerm b0 ns r =
let refs = Star3.lookupD1 ns . Branch._terms $ b0
@ -430,14 +474,14 @@ findShallowInBranch codebase b = do
+ (R.size . Branch.deepTypes $ Branch.head b)
b0 = Branch.head b
termEntries <- for (R.toList . Star3.d1 $ Branch._terms b0) $ \(r, ns) ->
ShallowTermEntry <$> termListEntry codebase b0 r (hqTerm b0 ns r)
ShallowTermEntry <$> termListEntry codebase (checkIsTestForBranch b0 r) r (hqTerm b0 ns r)
typeEntries <- for (R.toList . Star3.d1 $ Branch._types b0) $
\(r, ns) -> ShallowTypeEntry <$> typeListEntry codebase r (hqType b0 ns r)
let branchEntries =
[ ShallowBranchEntry
ns
(SBH.fullFromHash $ Branch.headHash b)
(defnCount b)
(Branch.headHash b)
(Just $ defnCount b)
| (ns, b) <- Map.toList $ Branch.nonEmptyChildren b0
]
patchEntries =
@ -451,6 +495,66 @@ findShallowInBranch codebase b = do
++ branchEntries
++ patchEntries
-- | Find all definitions and children reachable from the given 'V2Branch.Branch',
-- Note: this differs from 'lsBranch' in that it takes a shallow v2 branch,
-- As a result, it omits definition counts from child-namespaces in its results,
-- but doesn't require loading the entire sub-tree to do so.
lsShallowBranch ::
Monad m =>
Codebase m Symbol Ann ->
V2Branch.Branch m ->
m [ShallowListEntry Symbol Ann]
lsShallowBranch codebase b0 = do
hashLength <- Codebase.hashLength codebase
let hqTerm ::
( V2Branch.Branch m ->
V2Branch.NameSegment ->
Referent ->
HQ'.HashQualified NameSegment
)
hqTerm b ns r =
let refs = Map.lookup ns . V2Branch.terms $ b
in case length refs of
1 -> HQ'.fromName (Cv.namesegment2to1 ns)
_ -> HQ'.take hashLength $ HQ'.fromNamedReferent (Cv.namesegment2to1 ns) r
hqType ::
( V2Branch.Branch m ->
V2Branch.NameSegment ->
Reference ->
(HQ'.HashQualified NameSegment)
)
hqType b ns r =
let refs = Map.lookup ns . V2Branch.types $ b
in case length refs of
1 -> HQ'.fromName (Cv.namesegment2to1 ns)
_ -> HQ'.take hashLength $ HQ'.fromNamedReference (Cv.namesegment2to1 ns) r
let flattenRefs :: Map V2Branch.NameSegment (Map ref v) -> [(ref, V2Branch.NameSegment)]
flattenRefs m = do
(ns, refs) <- Map.toList m
r <- Map.keys refs
pure (r, ns)
termEntries <- for (flattenRefs $ V2Branch.terms b0) $ \(r, ns) -> do
isTest <- checkIsTestForV2Branch b0 r
v1Ref <- Cv.referent2to1 (Codebase.getDeclType codebase) r
ShallowTermEntry <$> termListEntry codebase isTest v1Ref (hqTerm b0 ns v1Ref)
typeEntries <- for (flattenRefs $ V2Branch.types b0) \(r, ns) -> do
let v1Ref = Cv.reference2to1 r
ShallowTypeEntry <$> typeListEntry codebase v1Ref (hqType b0 ns v1Ref)
let branchEntries =
[ ShallowBranchEntry (Cv.namesegment2to1 ns) (Cv.causalHash2to1 . V2Causal.causalHash $ h) Nothing
| (ns, h) <- Map.toList $ V2Branch.children b0
]
patchEntries =
[ ShallowPatchEntry (Cv.namesegment2to1 ns)
| (ns, _h) <- Map.toList $ V2Branch.patches b0
]
pure
. List.sortOn listEntryName
$ termEntries
++ typeEntries
++ branchEntries
++ patchEntries
termReferencesByShortHash ::
Monad m => Codebase m v a -> ShortHash -> m (Set Reference)
@ -757,6 +861,7 @@ prettyDefinitionsBySuffixes namesScope root renderWidth suffixifyBindings rt cod
ExceptT BackendError IO TermDefinition
)
mkTermDefinition r tm = do
let referent = Referent.Ref r
ts <- lift (Codebase.getTypeOfTerm codebase r)
let bn = bestNameForTerm @Symbol (PPE.suffixifiedPPE ppe) width (Referent.Ref r)
tag <-
@ -764,8 +869,8 @@ prettyDefinitionsBySuffixes namesScope root renderWidth suffixifyBindings rt cod
( termEntryTag
<$> termListEntry
codebase
(Branch.head branch)
(Referent.Ref r)
(checkIsTestForBranch (Branch.head branch) referent)
referent
(HQ'.NameOnly (NameSegment bn))
)
docs <- lift (docResults [r] $ docNames (NamesWithHistory.termName hqLength (Referent.Ref r) printNames))

View File

@ -164,7 +164,7 @@ serveFuzzyFind codebase mayRoot relativePath limit typeWidth query =
$ Backend.termEntryToNamedTerm ppe typeWidth te
)
)
<$> Backend.termListEntry codebase b0 r n
<$> Backend.termListEntry codebase (Backend.checkIsTestForBranch b0 r) r n
Backend.FoundTypeRef r -> do
te <- Backend.typeListEntry codebase r n
let namedType = Backend.typeEntryToNamedType te

View File

@ -9,7 +9,6 @@
module Unison.Server.Endpoints.NamespaceListing where
import Control.Error.Util ((??))
import Control.Monad.Except
import Data.Aeson
import Data.OpenApi (ToSchema)
@ -25,17 +24,22 @@ import Servant.Docs
ToSample (..),
)
import Servant.OpenApi ()
import qualified U.Codebase.Branch as V2Branch
import qualified U.Codebase.Causal as V2Causal
import qualified U.Util.Hash as Hash
import Unison.Codebase (Codebase)
import qualified Unison.Codebase as Codebase
import qualified Unison.Codebase.Branch as Branch
import qualified Unison.Codebase.Branch as V1Branch
import qualified Unison.Codebase.Causal as Causal
import qualified Unison.Codebase.Path as Path
import qualified Unison.Codebase.Path.Parse as Path
import Unison.Codebase.ShortBranchHash (ShortBranchHash)
import qualified Unison.Codebase.ShortBranchHash as SBH
import qualified Unison.Codebase.SqliteCodebase.Conversions as Cv
import qualified Unison.NameSegment as NameSegment
import Unison.Parser.Ann (Ann)
import Unison.Prelude
import qualified Unison.PrettyPrintEnv as PPE
import Unison.Server.Backend (Backend)
import qualified Unison.Server.Backend as Backend
import Unison.Server.Types
( APIGet,
@ -43,10 +47,9 @@ import Unison.Server.Types
NamedTerm (..),
NamedType (..),
NamespaceFQN,
Size,
UnisonHash,
UnisonName,
branchToUnisonHash,
v2CausalBranchToUnisonHash,
)
import Unison.Symbol (Symbol)
import Unison.Util.Pretty (Width)
@ -73,7 +76,7 @@ instance ToSample NamespaceListing where
NamespaceListing
"."
"#gjlk0dna8dongct6lsd19d1o9hi5n642t8jttga5e81e91fviqjdffem0tlddj7ahodjo5"
[Subnamespace $ NamedNamespace "base" "#19d1o9hi5n642t8jttg" 1244]
[Subnamespace $ NamedNamespace "base" "#19d1o9hi5n642t8jttg"]
)
]
@ -103,8 +106,7 @@ deriving instance ToSchema NamespaceObject
data NamedNamespace = NamedNamespace
{ namespaceName :: UnisonName,
namespaceHash :: UnisonHash,
namespaceSize :: Size
namespaceHash :: UnisonHash
}
deriving (Generic, Show)
@ -137,12 +139,11 @@ backendListEntryToNamespaceObject ppe typeWidth = \case
Backend.ShallowTermEntry te ->
TermObject $ Backend.termEntryToNamedTerm ppe typeWidth te
Backend.ShallowTypeEntry te -> TypeObject $ Backend.typeEntryToNamedType te
Backend.ShallowBranchEntry name hash size ->
Backend.ShallowBranchEntry name hash _size ->
Subnamespace $
NamedNamespace
{ namespaceName = NameSegment.toText name,
namespaceHash = "#" <> SBH.toText hash,
namespaceSize = size
namespaceHash = "#" <> Hash.toBase32HexText (Causal.unRawHash hash)
}
Backend.ShallowPatchEntry name ->
PatchObject . NamedPatch $ NameSegment.toText name
@ -153,14 +154,26 @@ serve ::
Maybe NamespaceFQN ->
Maybe NamespaceFQN ->
Backend.Backend IO NamespaceListing
serve codebase mayRoot mayRelativeTo mayNamespaceName =
serve codebase mayRootHash mayRelativeTo mayNamespaceName =
let -- Various helpers
errFromEither f = either (throwError . f) pure
parsePath :: String -> Backend IO Path.Path'
parsePath p = errFromEither (`Backend.BadNamespace` p) $ Path.parsePath' p
findShallow branch = Backend.findShallowInBranch codebase branch
findShallow ::
( V2Branch.Branch IO ->
IO [Backend.ShallowListEntry Symbol Ann]
)
findShallow branch = Backend.lsShallowBranch codebase branch
makeNamespaceListing ::
( PPE.PrettyPrintEnv ->
UnisonName ->
UnisonHash ->
[Backend.ShallowListEntry Symbol a] ->
ExceptT Backend.BackendError IO NamespaceListing
)
makeNamespaceListing ppe fqn hash entries =
pure . NamespaceListing fqn hash $
fmap
@ -168,15 +181,13 @@ serve codebase mayRoot mayRelativeTo mayNamespaceName =
entries
-- Lookup paths, root and listing and construct response
namespaceListing :: Backend IO NamespaceListing
namespaceListing = do
root <- case mayRoot of
Nothing -> lift (Codebase.getRootBranch codebase)
shallowRoot <- case mayRootHash of
Nothing -> liftIO (Codebase.getShallowRootBranch codebase)
Just sbh -> do
ea <- liftIO . runExceptT $ do
h <- Backend.expandShortBranchHash codebase sbh
mayBranch <- lift $ Codebase.getBranchForHash codebase h
mayBranch ?? Backend.CouldntLoadBranch h
liftEither ea
h <- Backend.expandShortBranchHash codebase sbh
liftIO $ Codebase.getShallowBranchForHash codebase (Cv.branchHash1to2 h)
-- Relative and Listing Path resolution
--
@ -197,14 +208,14 @@ serve codebase mayRoot mayRelativeTo mayNamespaceName =
let path = Path.fromPath' relativeToPath' <> Path.fromPath' namespacePath'
let path' = Path.toPath' path
-- Actually construct the NamespaceListing
let listingBranch = Branch.getAt' path root
hashLength <- liftIO $ Codebase.hashLength codebase
let shallowPPE = Backend.basicSuffixifiedNames hashLength root $ (Backend.Within $ Path.fromPath' path')
listingCausal <-
(liftIO $ Codebase.shallowBranchAtPath path shallowRoot) >>= \case
Nothing -> pure $ Cv.causalbranch1to2 (V1Branch.empty)
Just lc -> pure lc
listingBranch <- liftIO $ V2Causal.value listingCausal
shallowPPE <- liftIO $ Backend.shallowPPE codebase listingBranch
let listingFQN = Path.toText . Path.unabsolute . either id (Path.Absolute . Path.unrelative) $ Path.unPath' path'
let listingHash = branchToUnisonHash listingBranch
let listingHash = v2CausalBranchToUnisonHash listingCausal
listingEntries <- lift (findShallow listingBranch)
makeNamespaceListing shallowPPE listingFQN listingHash listingEntries

View File

@ -25,13 +25,14 @@ import Servant.Docs
ToParam (..),
ToSample (..),
)
import qualified U.Util.Hash as Hash
import Unison.Codebase (Codebase)
import qualified Unison.Codebase as Codebase
import qualified Unison.Codebase.Branch as Branch
import qualified Unison.Codebase.Causal.Type as Causal
import qualified Unison.Codebase.Path as Path
import qualified Unison.Codebase.Path.Parse as Path
import Unison.Codebase.ShortBranchHash (ShortBranchHash)
import qualified Unison.Codebase.ShortBranchHash as SBH
import qualified Unison.NameSegment as NameSegment
import Unison.Parser.Ann (Ann)
import Unison.Prelude
@ -103,12 +104,12 @@ backendListEntryToProjectListing ::
Backend.ShallowListEntry Symbol a ->
Maybe ProjectListing
backendListEntryToProjectListing owner = \case
Backend.ShallowBranchEntry name hash _ ->
Backend.ShallowBranchEntry name hash _size ->
Just $
ProjectListing
{ owner = owner,
name = NameSegment.toText name,
hash = "#" <> SBH.toText hash
hash = "#" <> Hash.toBase32HexText (Causal.unRawHash hash)
}
_ -> Nothing
@ -116,7 +117,7 @@ entryToOwner ::
Backend.ShallowListEntry Symbol a ->
Maybe ProjectOwner
entryToOwner = \case
Backend.ShallowBranchEntry name _ _ ->
Backend.ShallowBranchEntry name _ _size ->
Just $ ProjectOwner $ NameSegment.toText name
_ -> Nothing
@ -140,7 +141,7 @@ serve codebase mayRoot mayOwner = projects
mayBranch ?? Backend.CouldntLoadBranch h
liftEither ea
ownerEntries <- findShallow root
ownerEntries <- lift $ findShallow root
-- If an owner is provided, we only want projects belonging to them
let owners =
case mayOwner of
@ -154,14 +155,14 @@ serve codebase mayRoot mayOwner = projects
ownerPath' <- (parsePath . Text.unpack) ownerName
let path = Path.fromPath' ownerPath'
let ownerBranch = Branch.getAt' path root
entries <- findShallow ownerBranch
entries <- lift $ findShallow ownerBranch
pure $ mapMaybe (backendListEntryToProjectListing owner) entries
-- Minor helpers
findShallow :: Branch.Branch m -> Backend m [Backend.ShallowListEntry Symbol Ann]
findShallow :: Branch.Branch m -> m [Backend.ShallowListEntry Symbol Ann]
findShallow branch =
lift (Backend.findShallowInBranch codebase branch)
Backend.lsBranch codebase branch
parsePath :: String -> Backend m Path.Path'
parsePath p =

View File

@ -27,6 +27,9 @@ import Servant.API
JSON,
addHeader,
)
import qualified U.Codebase.Branch as V2Branch
import qualified U.Codebase.Causal as V2Causal
import qualified U.Codebase.HashTags as V2
import qualified Unison.Codebase.Branch as Branch
import qualified Unison.Codebase.Causal as Causal
import Unison.Codebase.Editor.DisplayObject
@ -265,3 +268,7 @@ setCacheControl = addHeader @"Cache-Control" "public"
branchToUnisonHash :: Branch.Branch m -> UnisonHash
branchToUnisonHash b =
("#" <>) . Hash.base32Hex . Causal.unRawHash $ Branch.headHash b
v2CausalBranchToUnisonHash :: V2Branch.CausalBranch m -> UnisonHash
v2CausalBranchToUnisonHash b =
("#" <>) . Hash.base32Hex . V2.unCausalHash $ V2Causal.causalHash b

View File

@ -93,10 +93,12 @@ library
, servant-server
, text
, transformers
, unison-codebase
, unison-core1
, unison-parser-typechecker
, unison-prelude
, unison-pretty-printer
, unison-util
, unison-util-relation
, unliftio
, uri-encode