mirror of
https://github.com/unisonweb/unison.git
synced 2024-09-19 06:17:33 +03:00
Re-implement Browse API to avoid loading entire codebase root (#3054)
Swap Browse API to use V2 branches.
This commit is contained in:
parent
3bfb412a4d
commit
d79e396c44
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
..
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ module U.Util.Hash
|
||||
fromBase32Hex,
|
||||
fromByteString,
|
||||
toBase32Hex,
|
||||
toBase32HexText,
|
||||
toByteString,
|
||||
)
|
||||
where
|
||||
|
@ -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 =
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user