@@ -42,8 +42,10 @@ import Share.Web.Share.Contributions.API
4242import Share.Web.Share.Contributions.API qualified as API
4343import Share.Web.Share.Contributions.Types
4444import Share.Web.Share.Diffs.Impl qualified as Diffs
45- import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (.. ))
45+ import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (.. ), ShareTermDiffResponse ( .. ), ShareTypeDiffResponse ( .. ) )
4646import Share.Web.Share.Types (UserDisplayInfo )
47+ import Unison.Name (Name )
48+ import Unison.Syntax.Name qualified as Name
4749
4850contributionsByProjectServer :: Maybe Session -> UserHandle -> ProjectSlug -> ServerT API. ContributionsByProjectAPI WebApp
4951contributionsByProjectServer session handle projectSlug =
@@ -62,7 +64,10 @@ contributionsByProjectServer session handle projectSlug =
6264 addServerTag (Proxy @ API. ContributionResourceServer ) " contribution-number" (IDs. toText contributionNumber) $
6365 getContributionByNumberEndpoint session handle projectSlug contributionNumber
6466 :<|> updateContributionByNumberEndpoint session handle projectSlug contributionNumber
65- :<|> contributionDiffEndpoint session handle projectSlug contributionNumber
67+ :<|> ( contributionDiffTermsEndpoint session handle projectSlug contributionNumber
68+ :<|> contributionDiffTypesEndpoint session handle projectSlug contributionNumber
69+ :<|> contributionDiffEndpoint session handle projectSlug contributionNumber
70+ )
6671 :<|> mergeContributionEndpoint session handle projectSlug contributionNumber
6772 :<|> timelineServer contributionNumber
6873 in listContributionsByProjectEndpoint session handle projectSlug
@@ -235,9 +240,9 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr
235240 newPBSH <- Codebase. runCodebaseTransactionOrRespondError newCodebase $ do
236241 lift $ Q. projectBranchShortHandByBranchId newBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Source branch not found" )
237242
238- let cacheKeys = [IDs. toText contributionId, IDs. toText newPBSH, IDs. toText oldPBSH, Caching. causalIdCacheKey newBranchCausalId, Caching. causalIdCacheKey oldBranchCausalId]
243+ let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId
244+ let cacheKeys = [IDs. toText contributionId, IDs. toText newPBSH, IDs. toText oldPBSH, Caching. causalIdCacheKey newBranchCausalId, Caching. causalIdCacheKey oldCausalId]
239245 Caching. cachedResponse authZReceipt " contribution-diff" cacheKeys do
240- let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId
241246 namespaceDiff <- Diffs. diffCausals authZReceipt oldCausalId newBranchCausalId
242247 (newBranchCausalHash, oldCausalHash) <- PG. runTransaction $ do
243248 newBranchCausalHash <- CausalQ. expectCausalHashesByIdsOf id newBranchCausalId
@@ -255,6 +260,96 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr
255260 where
256261 projectShorthand = IDs. ProjectShortHand {userHandle, projectSlug}
257262
263+ contributionDiffTermsEndpoint ::
264+ Maybe Session ->
265+ UserHandle ->
266+ ProjectSlug ->
267+ IDs. ContributionNumber ->
268+ Name ->
269+ Name ->
270+ WebApp (Cached JSON ShareTermDiffResponse )
271+ contributionDiffTermsEndpoint (AuthN. MaybeAuthedUserID mayCallerUserId) userHandle projectSlug contributionNumber oldTermName newTermName =
272+ do
273+ ( project,
274+ Contribution {contributionId, bestCommonAncestorCausalId},
275+ oldBranch@ Branch {causal = oldBranchCausalId, branchId = oldBranchId},
276+ newBranch@ Branch {causal = newBranchCausalId, branchId = newBranchId}
277+ ) <- PG. runTransactionOrRespondError $ do
278+ project@ Project {projectId} <- Q. projectByShortHand projectShorthand `whenNothingM` throwError (EntityMissing (ErrorID " project:missing" ) " Project not found" )
279+ contribution@ Contribution {sourceBranchId = newBranchId, targetBranchId = oldBranchId} <- ContributionsQ. contributionByProjectIdAndNumber projectId contributionNumber `whenNothingM` throwError (EntityMissing (ErrorID " contribution:missing" ) " Contribution not found" )
280+ newBranch <- Q. branchById newBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Source branch not found" )
281+ oldBranch <- Q. branchById oldBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Target branch not found" )
282+ pure (project, contribution, oldBranch, newBranch)
283+ authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkContributionRead mayCallerUserId project
284+ let oldCodebase = Codebase. codebaseForProjectBranch authZReceipt project oldBranch
285+ let newCodebase = Codebase. codebaseForProjectBranch authZReceipt project newBranch
286+ oldPBSH <- Codebase. runCodebaseTransactionOrRespondError oldCodebase $ do
287+ lift $ Q. projectBranchShortHandByBranchId oldBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Target branch not found" )
288+ newPBSH <- Codebase. runCodebaseTransactionOrRespondError newCodebase $ do
289+ lift $ Q. projectBranchShortHandByBranchId newBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Source branch not found" )
290+ let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId
291+ let cacheKeys = [IDs. toText contributionId, IDs. toText newPBSH, IDs. toText oldPBSH, Caching. causalIdCacheKey newBranchCausalId, Caching. causalIdCacheKey oldCausalId, Name. toText oldTermName, Name. toText newTermName]
292+ Caching. cachedResponse authZReceipt " contribution-diff-terms" cacheKeys do
293+ (oldBranchHashId, newBranchHashId) <- PG. runTransaction $ CausalQ. expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId)
294+ (oldTerm, newTerm, displayObjDiff) <- Diffs. diffTerms authZReceipt (oldCodebase, oldBranchHashId, oldTermName) (newCodebase, newBranchHashId, newTermName)
295+ pure $
296+ ShareTermDiffResponse
297+ { project = projectShorthand,
298+ oldBranch = IDs. IsBranchShortHand $ IDs. projectBranchShortHandToBranchShortHand oldPBSH,
299+ newBranch = IDs. IsBranchShortHand $ IDs. projectBranchShortHandToBranchShortHand newPBSH,
300+ oldTerm = oldTerm,
301+ newTerm = newTerm,
302+ diff = displayObjDiff
303+ }
304+ where
305+ projectShorthand :: IDs. ProjectShortHand
306+ projectShorthand = IDs. ProjectShortHand {userHandle, projectSlug}
307+
308+ contributionDiffTypesEndpoint ::
309+ Maybe Session ->
310+ UserHandle ->
311+ ProjectSlug ->
312+ IDs. ContributionNumber ->
313+ Name ->
314+ Name ->
315+ WebApp (Cached JSON ShareTypeDiffResponse )
316+ contributionDiffTypesEndpoint (AuthN. MaybeAuthedUserID mayCallerUserId) userHandle projectSlug contributionNumber oldTypeName newTypeName =
317+ do
318+ ( project,
319+ Contribution {contributionId, bestCommonAncestorCausalId},
320+ oldBranch@ Branch {causal = oldBranchCausalId, branchId = oldBranchId},
321+ newBranch@ Branch {causal = newBranchCausalId, branchId = newBranchId}
322+ ) <- PG. runTransactionOrRespondError $ do
323+ project@ Project {projectId} <- Q. projectByShortHand projectShorthand `whenNothingM` throwError (EntityMissing (ErrorID " project:missing" ) " Project not found" )
324+ contribution@ Contribution {sourceBranchId = newBranchId, targetBranchId = oldBranchId} <- ContributionsQ. contributionByProjectIdAndNumber projectId contributionNumber `whenNothingM` throwError (EntityMissing (ErrorID " contribution:missing" ) " Contribution not found" )
325+ newBranch <- Q. branchById newBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Source branch not found" )
326+ oldBranch <- Q. branchById oldBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Target branch not found" )
327+ pure (project, contribution, oldBranch, newBranch)
328+ authZReceipt <- AuthZ. permissionGuard $ AuthZ. checkContributionRead mayCallerUserId project
329+ let oldCodebase = Codebase. codebaseForProjectBranch authZReceipt project oldBranch
330+ let newCodebase = Codebase. codebaseForProjectBranch authZReceipt project newBranch
331+ oldPBSH <- Codebase. runCodebaseTransactionOrRespondError oldCodebase $ do
332+ lift $ Q. projectBranchShortHandByBranchId oldBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Target branch not found" )
333+ newPBSH <- Codebase. runCodebaseTransactionOrRespondError newCodebase $ do
334+ lift $ Q. projectBranchShortHandByBranchId newBranchId `whenNothingM` throwError (EntityMissing (ErrorID " branch:missing" ) " Source branch not found" )
335+ let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId
336+ let cacheKeys = [IDs. toText contributionId, IDs. toText newPBSH, IDs. toText oldPBSH, Caching. causalIdCacheKey newBranchCausalId, Caching. causalIdCacheKey oldCausalId, Name. toText oldTypeName, Name. toText newTypeName]
337+ Caching. cachedResponse authZReceipt " contribution-diff-types" cacheKeys do
338+ (oldBranchHashId, newBranchHashId) <- PG. runTransaction $ CausalQ. expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId)
339+ (oldType, newType, displayObjDiff) <- Diffs. diffTypes authZReceipt (oldCodebase, oldBranchHashId, oldTypeName) (newCodebase, newBranchHashId, newTypeName)
340+ pure $
341+ ShareTypeDiffResponse
342+ { project = projectShorthand,
343+ oldBranch = IDs. IsBranchShortHand $ IDs. projectBranchShortHandToBranchShortHand oldPBSH,
344+ newBranch = IDs. IsBranchShortHand $ IDs. projectBranchShortHandToBranchShortHand newPBSH,
345+ oldType = oldType,
346+ newType = newType,
347+ diff = displayObjDiff
348+ }
349+ where
350+ projectShorthand :: IDs. ProjectShortHand
351+ projectShorthand = IDs. ProjectShortHand {userHandle, projectSlug}
352+
258353mergeContributionEndpoint ::
259354 Maybe Session ->
260355 UserHandle ->
0 commit comments