@@ -11,20 +11,25 @@ import Data.ByteString.Lazy qualified as BL
11
11
import Data.Map qualified as Map
12
12
import Data.Text qualified as Text
13
13
import Data.Text.Encoding qualified as Text
14
- import Share.Branch (Branch (.. ), defaultBranchShorthand )
14
+ import Servant
15
+ import Share.Branch (defaultBranchShorthand )
16
+ import Share.Branch qualified as Branch
17
+ import Share.Codebase (CodebaseEnv )
18
+ import Share.Codebase qualified as Codebase
15
19
import Share.IDs (PrefixedHash (.. ), ProjectSlug (.. ), UserHandle , UserId )
16
20
import Share.IDs qualified as IDs
17
21
import Share.OAuth.Session
18
22
import Share.Postgres qualified as PG
19
23
import Share.Postgres.Causal.Queries qualified as CausalQ
20
- import Share.Postgres.IDs (CausalId )
24
+ import Share.Postgres.IDs (BranchHashId , CausalId )
25
+ import Share.Postgres.NameLookups.Ops qualified as NameLookupOps
21
26
import Share.Postgres.Ops qualified as PGO
22
27
import Share.Postgres.Projects.Queries qualified as ProjectsQ
23
28
import Share.Postgres.Queries qualified as Q
24
29
import Share.Postgres.Users.Queries qualified as UsersQ
25
30
import Share.Prelude
26
31
import Share.Project (Project (.. ))
27
- import Share.Release ( Release ( .. ))
32
+ import Share.Release qualified as Release
28
33
import Share.User (User (.. ))
29
34
import Share.Utils.API ((:++) (.. ))
30
35
import Share.Utils.Caching (Cached )
@@ -43,7 +48,17 @@ import Share.Web.Share.Projects.Types
43
48
import Share.Web.Share.Releases.Impl (getProjectReleaseReadmeEndpoint , releasesServer )
44
49
import Share.Web.Share.Tickets.Impl (ticketsByProjectServer )
45
50
import Share.Web.Share.Types
46
- import Servant
51
+ import Unison.Codebase.Path qualified as Path
52
+ import Unison.Name (Name )
53
+ import Unison.PrettyPrintEnvDecl qualified as PPED
54
+ import Unison.PrettyPrintEnvDecl.Postgres qualified as PPEPostgres
55
+ import Unison.Server.Backend.DefinitionDiff qualified as DefinitionDiff
56
+ import Unison.Server.NameSearch.Postgres qualified as PGNameSearch
57
+ import Unison.Server.Orphans ()
58
+ import Unison.Server.Share.Definitions qualified as Definitions
59
+ import Unison.Server.Types (TermDefinition (.. ), TypeDefinition (.. ))
60
+ import Unison.Syntax.Name qualified as Name
61
+ import Unison.Util.Pretty (Width )
47
62
48
63
data ProjectErrors
49
64
= MaintainersAlreadyExist [UserId ]
@@ -91,7 +106,10 @@ projectServer session handle =
91
106
:<|> releasesServer session handle slug
92
107
:<|> contributionsByProjectServer session handle slug
93
108
:<|> ticketsByProjectServer session handle slug
94
- :<|> diffNamespacesEndpoint session handle slug
109
+ :<|> ( diffNamespacesEndpoint session handle slug
110
+ :<|> diffTermsEndpoint session handle slug
111
+ :<|> diffTypesEndpoint session handle slug
112
+ )
95
113
:<|> createProjectEndpoint session handle slug
96
114
:<|> updateProjectEndpoint session handle slug
97
115
:<|> deleteProjectEndpoint session handle slug
@@ -142,8 +160,8 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project
142
160
project@ Project {projectId} <- PG. runTransactionOrRespondError do
143
161
Q. projectByShortHand projectShortHand `whenNothingM` throwError (EntityMissing (ErrorID " project-not-found" ) (" Project not found: " <> IDs. toText @ IDs. ProjectShortHand projectShortHand))
144
162
authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkProjectBranchDiff callerUserId project
145
- oldCausalId <- resolveBranchOrRelease projectId oldShortHand
146
- newCausalId <- resolveBranchOrRelease projectId newShortHand
163
+ (_, oldCausalId, _oldBranchId) <- namespaceHashForBranchOrRelease authZReceipt project oldShortHand
164
+ (_, newCausalId, _newBranchId) <- namespaceHashForBranchOrRelease authZReceipt project newShortHand
147
165
148
166
let cacheKeys = [IDs. toText projectId, IDs. toText oldShortHand, IDs. toText newShortHand, Caching. causalIdCacheKey oldCausalId, Caching. causalIdCacheKey newCausalId]
149
167
Caching. cachedResponse authZReceipt " project-diff-namespaces" cacheKeys do
@@ -163,16 +181,113 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project
163
181
}
164
182
where
165
183
projectShortHand = IDs. ProjectShortHand {userHandle, projectSlug}
166
- resolveBranchOrRelease :: IDs. ProjectId -> IDs. BranchOrReleaseShortHand -> WebApp CausalId
167
- resolveBranchOrRelease projectId = \ case
168
- IDs. IsBranchShortHand branchShortHand -> do
169
- PG. runTransactionOrRespondError $ do
170
- Branch {causal = branchHead} <- Q. branchByProjectIdAndShortHand projectId branchShortHand `whenNothingM` throwError (EntityMissing (ErrorID " branch-not-found" ) (" Branch not found: " <> IDs. toText @ IDs. BranchShortHand branchShortHand))
171
- pure branchHead
172
- IDs. IsReleaseShortHand releaseShortHand -> do
173
- PG. runTransactionOrRespondError $ do
174
- Release {squashedCausal = releaseHead} <- Q. releaseByProjectIdAndReleaseShortHand projectId releaseShortHand `whenNothingM` throwError (EntityMissing (ErrorID " release-not-found" ) (" Release not found: " <> IDs. toText @ IDs. ReleaseShortHand releaseShortHand))
175
- pure releaseHead
184
+
185
+ diffTermsEndpoint ::
186
+ Maybe Session ->
187
+ UserHandle ->
188
+ ProjectSlug ->
189
+ IDs. BranchOrReleaseShortHand ->
190
+ IDs. BranchOrReleaseShortHand ->
191
+ Name ->
192
+ Name ->
193
+ WebApp ShareTermDiffResponse
194
+ diffTermsEndpoint (AuthN. MaybeAuthedUserID callerUserId) userHandle projectSlug oldShortHand newShortHand oldTermName newTermName =
195
+ do
196
+ project <- PG. runTransactionOrRespondError do
197
+ Q. projectByShortHand projectShortHand `whenNothingM` throwError (EntityMissing (ErrorID " project-not-found" ) (" Project not found: " <> IDs. toText @ IDs. ProjectShortHand projectShortHand))
198
+ authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkProjectBranchDiff callerUserId project
199
+ oldTerm@ (TermDefinition {termDefinition = oldDisplayObj}) <- getTermDefinition authZReceipt project oldShortHand oldTermName `whenNothingM` respondError (EntityMissing (ErrorID " term-not-found" ) (" Term not found: " <> IDs. toText oldShortHand <> " :" <> Name. toText oldTermName))
200
+ newTerm@ (TermDefinition {termDefinition = newDisplayObj}) <- getTermDefinition authZReceipt project newShortHand newTermName `whenNothingM` respondError (EntityMissing (ErrorID " term-not-found" ) (" Term not found: " <> IDs. toText newShortHand <> " :" <> Name. toText newTermName))
201
+ let termDiffDisplayObject = DefinitionDiff. diffDisplayObjects oldDisplayObj newDisplayObj
202
+ pure $
203
+ ShareTermDiffResponse
204
+ { project = projectShortHand,
205
+ oldBranch = oldShortHand,
206
+ newBranch = newShortHand,
207
+ oldTerm = oldTerm,
208
+ newTerm = newTerm,
209
+ diff = termDiffDisplayObject
210
+ }
211
+ where
212
+ renderWidth :: Width
213
+ renderWidth = 80
214
+ getTermDefinition :: AuthZ. AuthZReceipt -> Project -> IDs. BranchOrReleaseShortHand -> Name -> WebApp (Maybe TermDefinition )
215
+ getTermDefinition authZReceipt project shorthand name = do
216
+ (codebase, _causalId, bhId) <- namespaceHashForBranchOrRelease authZReceipt project shorthand
217
+ let perspective = Path. empty
218
+ (namesPerspective, Identity relocatedName) <- PG. runTransaction $ NameLookupOps. relocateToNameRoot perspective (Identity name) bhId
219
+ let ppedBuilder deps = (PPED. biasTo [name]) <$> lift (PPEPostgres. ppedForReferences namesPerspective deps)
220
+ let nameSearch = PGNameSearch. nameSearchForPerspective namesPerspective
221
+ rt <- Codebase. codebaseRuntime codebase
222
+ Codebase. runCodebaseTransaction codebase do
223
+ Definitions. termDefinitionByName ppedBuilder nameSearch renderWidth rt relocatedName
224
+
225
+ projectShortHand :: IDs. ProjectShortHand
226
+ projectShortHand = IDs. ProjectShortHand {userHandle, projectSlug}
227
+
228
+ diffTypesEndpoint ::
229
+ Maybe Session ->
230
+ UserHandle ->
231
+ ProjectSlug ->
232
+ IDs. BranchOrReleaseShortHand ->
233
+ IDs. BranchOrReleaseShortHand ->
234
+ Name ->
235
+ Name ->
236
+ WebApp ShareTypeDiffResponse
237
+ diffTypesEndpoint (AuthN. MaybeAuthedUserID callerUserId) userHandle projectSlug oldShortHand newShortHand oldTypeName newTypeName =
238
+ do
239
+ project <- PG. runTransactionOrRespondError do
240
+ Q. projectByShortHand projectShortHand `whenNothingM` throwError (EntityMissing (ErrorID " project-not-found" ) (" Project not found: " <> IDs. toText @ IDs. ProjectShortHand projectShortHand))
241
+ authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkProjectBranchDiff callerUserId project
242
+ sourceType@ (TypeDefinition {typeDefinition = sourceDisplayObj}) <- getTypeDefinition authZReceipt project oldShortHand oldTypeName `whenNothingM` respondError (EntityMissing (ErrorID " type-not-found" ) (" Type not found: " <> IDs. toText oldShortHand <> " :" <> Name. toText oldTypeName))
243
+ newType@ (TypeDefinition {typeDefinition = newDisplayObj}) <- getTypeDefinition authZReceipt project newShortHand newTypeName `whenNothingM` respondError (EntityMissing (ErrorID " type-not-found" ) (" Type not found: " <> IDs. toText newShortHand <> " :" <> Name. toText newTypeName))
244
+ let typeDiffDisplayObject = DefinitionDiff. diffDisplayObjects sourceDisplayObj newDisplayObj
245
+ pure $
246
+ ShareTypeDiffResponse
247
+ { project = projectShortHand,
248
+ oldBranch = oldShortHand,
249
+ newBranch = newShortHand,
250
+ oldType = sourceType,
251
+ newType = newType,
252
+ diff = typeDiffDisplayObject
253
+ }
254
+ where
255
+ renderWidth :: Width
256
+ renderWidth = 80
257
+ getTypeDefinition :: AuthZ. AuthZReceipt -> Project -> IDs. BranchOrReleaseShortHand -> Name -> WebApp (Maybe TypeDefinition )
258
+ getTypeDefinition authZReceipt project shorthand name = do
259
+ (codebase, _causalId, bhId) <- namespaceHashForBranchOrRelease authZReceipt project shorthand
260
+ let perspective = Path. empty
261
+ (namesPerspective, Identity relocatedName) <- PG. runTransaction $ NameLookupOps. relocateToNameRoot perspective (Identity name) bhId
262
+ let ppedBuilder deps = (PPED. biasTo [name]) <$> lift (PPEPostgres. ppedForReferences namesPerspective deps)
263
+ let nameSearch = PGNameSearch. nameSearchForPerspective namesPerspective
264
+ rt <- Codebase. codebaseRuntime codebase
265
+ Codebase. runCodebaseTransaction codebase do
266
+ Definitions. typeDefinitionByName ppedBuilder nameSearch renderWidth rt relocatedName
267
+
268
+ projectShortHand :: IDs. ProjectShortHand
269
+ projectShortHand = IDs. ProjectShortHand {userHandle, projectSlug}
270
+
271
+ namespaceHashForBranchOrRelease :: AuthZ. AuthZReceipt -> Project -> IDs. BranchOrReleaseShortHand -> WebApp (CodebaseEnv , CausalId , BranchHashId )
272
+ namespaceHashForBranchOrRelease authZReceipt Project {projectId, ownerUserId = projectOwnerUserId} = \ case
273
+ IDs. IsBranchShortHand branchShortHand -> do
274
+ PG. runTransactionOrRespondError $ do
275
+ branch <- Q. branchByProjectIdAndShortHand projectId branchShortHand `whenNothingM` throwError (EntityMissing (ErrorID " branch-not-found" ) (" Branch not found: " <> IDs. toText @ IDs. BranchShortHand branchShortHand))
276
+ let causalId = Branch. causal branch
277
+ let codebaseLoc = Codebase. codebaseLocationForProjectBranchCodebase projectOwnerUserId (Branch. contributorId branch)
278
+ let codebase = Codebase. codebaseEnv authZReceipt codebaseLoc
279
+ Codebase. codebaseMToTransaction codebase do
280
+ branchHashId <- CausalQ. expectNamespaceIdForCausal causalId
281
+ pure (codebase, causalId, branchHashId)
282
+ IDs. IsReleaseShortHand releaseShortHand -> do
283
+ PG. runTransactionOrRespondError $ do
284
+ release <- Q. releaseByProjectIdAndReleaseShortHand projectId releaseShortHand `whenNothingM` throwError (EntityMissing (ErrorID " release-not-found" ) (" Release not found: " <> IDs. toText @ IDs. ReleaseShortHand releaseShortHand))
285
+ let causalId = Release. squashedCausal release
286
+ let codebaseLoc = Codebase. codebaseLocationForProjectRelease projectOwnerUserId
287
+ let codebase = Codebase. codebaseEnv authZReceipt codebaseLoc
288
+ Codebase. codebaseMToTransaction codebase do
289
+ branchHashId <- CausalQ. expectNamespaceIdForCausal causalId
290
+ pure (codebase, causalId, branchHashId)
176
291
177
292
createProjectEndpoint :: Maybe Session -> UserHandle -> ProjectSlug -> CreateProjectRequest -> WebApp CreateProjectResponse
178
293
createProjectEndpoint (AuthN. MaybeAuthedUserID callerUserId) userHandle projectSlug req = do
0 commit comments