mirror of
https://code.naskya.net/repos/ndqEd
synced 2025-01-30 04:37:51 +09:00
232 lines
7.4 KiB
Haskell
232 lines
7.4 KiB
Haskell
{- This file is part of Vervis.
|
|
-
|
|
- Written in 2020 by fr33domlover <fr33domlover@riseup.net>.
|
|
-
|
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
|
-
|
|
- The author(s) have dedicated all copyright and related and neighboring
|
|
- rights to this software to the public domain worldwide. This software is
|
|
- distributed without any warranty.
|
|
-
|
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
|
- with this software. If not, see
|
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
-}
|
|
|
|
module Vervis.Patch
|
|
( getSharerProposal
|
|
, getSharerProposal404
|
|
, getRepoProposal
|
|
, getRepoProposal404
|
|
)
|
|
where
|
|
|
|
import Control.Monad
|
|
import Control.Monad.IO.Class
|
|
import Control.Monad.Trans.Class
|
|
import Control.Monad.Trans.Maybe
|
|
import Control.Monad.Trans.Reader
|
|
import Data.List.NonEmpty (NonEmpty, nonEmpty)
|
|
import Data.Maybe
|
|
import Data.Traversable
|
|
import Database.Persist
|
|
import Database.Persist.Sql
|
|
import Yesod.Core
|
|
|
|
import Yesod.Hashids
|
|
|
|
import Data.Either.Local
|
|
import Database.Persist.Local
|
|
|
|
import Vervis.Foundation
|
|
import Vervis.Model
|
|
import Vervis.Model.Ident
|
|
|
|
getResolved
|
|
:: MonadIO m
|
|
=> LocalTicketId
|
|
-> ReaderT SqlBackend m
|
|
(Maybe
|
|
( Entity TicketResolve
|
|
, Either (Entity TicketResolveLocal) (Entity TicketResolveRemote)
|
|
)
|
|
)
|
|
getResolved ltid = do
|
|
metr <- getBy $ UniqueTicketResolve ltid
|
|
for metr $ \ etr@(Entity trid _) ->
|
|
(etr,) <$>
|
|
requireEitherAlt
|
|
(getBy $ UniqueTicketResolveLocal trid)
|
|
(getBy $ UniqueTicketResolveRemote trid)
|
|
"No TRX"
|
|
"Both TRL and TRR"
|
|
|
|
getSharerProposal
|
|
:: MonadIO m
|
|
=> ShrIdent
|
|
-> TicketAuthorLocalId
|
|
-> ReaderT SqlBackend m
|
|
( Maybe
|
|
( Entity TicketAuthorLocal
|
|
, Entity LocalTicket
|
|
, Entity Ticket
|
|
, Either
|
|
( Entity TicketContextLocal
|
|
, Entity TicketRepoLocal
|
|
)
|
|
( Entity TicketProjectRemote
|
|
, Maybe (Entity TicketProjectRemoteAccept)
|
|
)
|
|
, Maybe
|
|
( Entity TicketResolve
|
|
, Either
|
|
(Entity TicketResolveLocal)
|
|
(Entity TicketResolveRemote)
|
|
)
|
|
, NonEmpty BundleId
|
|
)
|
|
)
|
|
getSharerProposal shr talid = runMaybeT $ do
|
|
pid <- do
|
|
sid <- MaybeT $ getKeyBy $ UniqueSharer shr
|
|
MaybeT $ getKeyBy $ UniquePersonIdent sid
|
|
tal <- MaybeT $ get talid
|
|
guard $ ticketAuthorLocalAuthor tal == pid
|
|
let ltid = ticketAuthorLocalTicket tal
|
|
lt <- lift $ getJust ltid
|
|
let tid = localTicketTicket lt
|
|
t <- lift $ getJust tid
|
|
bnids <-
|
|
MaybeT $
|
|
nonEmpty <$> selectKeysList [BundleTicket ==. tid] [Desc BundleId]
|
|
repo <-
|
|
requireEitherAlt
|
|
(do mtcl <- lift $ getBy $ UniqueTicketContextLocal tid
|
|
for mtcl $ \ etcl@(Entity tclid _) -> do
|
|
etrl <- MaybeT $ getBy $ UniqueTicketRepoLocal tclid
|
|
mtup1 <- lift $ getBy $ UniqueTicketUnderProjectProject tclid
|
|
mtup2 <- lift $ getBy $ UniqueTicketUnderProjectAuthor talid
|
|
unless (isJust mtup1 == isJust mtup2) $
|
|
error "TUP points to unrelated TAL and TCL!"
|
|
guard $ not $ isJust mtup1
|
|
return (etcl, etrl)
|
|
)
|
|
(do mtpr <- lift $ getBy $ UniqueTicketProjectRemote talid
|
|
lift $ for mtpr $ \ etpr@(Entity tprid _) ->
|
|
(etpr,) <$> getBy (UniqueTicketProjectRemoteAccept tprid)
|
|
)
|
|
"MR doesn't have context"
|
|
"MR has both local and remote context"
|
|
mresolved <- lift $ getResolved ltid
|
|
return (Entity talid tal, Entity ltid lt, Entity tid t, repo, mresolved, bnids)
|
|
|
|
getSharerProposal404
|
|
:: ShrIdent
|
|
-> KeyHashid TicketAuthorLocal
|
|
-> AppDB
|
|
( Entity TicketAuthorLocal
|
|
, Entity LocalTicket
|
|
, Entity Ticket
|
|
, Either
|
|
( Entity TicketContextLocal
|
|
, Entity TicketRepoLocal
|
|
)
|
|
( Entity TicketProjectRemote
|
|
, Maybe (Entity TicketProjectRemoteAccept)
|
|
)
|
|
, Maybe
|
|
( Entity TicketResolve
|
|
, Either
|
|
(Entity TicketResolveLocal)
|
|
(Entity TicketResolveRemote)
|
|
)
|
|
, NonEmpty BundleId
|
|
)
|
|
getSharerProposal404 shr talkhid = do
|
|
talid <- decodeKeyHashid404 talkhid
|
|
mpatch <- getSharerProposal shr talid
|
|
case mpatch of
|
|
Nothing -> notFound
|
|
Just patch -> return patch
|
|
|
|
getRepoProposal
|
|
:: MonadIO m
|
|
=> ShrIdent
|
|
-> RpIdent
|
|
-> LocalTicketId
|
|
-> ReaderT SqlBackend m
|
|
( Maybe
|
|
( Entity Sharer
|
|
, Entity Repo
|
|
, Entity Ticket
|
|
, Entity LocalTicket
|
|
, Entity TicketContextLocal
|
|
, Entity TicketRepoLocal
|
|
, Either
|
|
(Entity TicketAuthorLocal, Entity TicketUnderProject)
|
|
(Entity TicketAuthorRemote)
|
|
, Maybe
|
|
( Entity TicketResolve
|
|
, Either
|
|
(Entity TicketResolveLocal)
|
|
(Entity TicketResolveRemote)
|
|
)
|
|
, NonEmpty BundleId
|
|
)
|
|
)
|
|
getRepoProposal shr rp ltid = runMaybeT $ do
|
|
es@(Entity sid _) <- MaybeT $ getBy $ UniqueSharer shr
|
|
er@(Entity rid _) <- MaybeT $ getBy $ UniqueRepo rp sid
|
|
lt <- MaybeT $ get ltid
|
|
let tid = localTicketTicket lt
|
|
t <- MaybeT $ get tid
|
|
etcl@(Entity tclid _) <- MaybeT $ getBy $ UniqueTicketContextLocal tid
|
|
etrl@(Entity _ trl) <- MaybeT $ getBy $ UniqueTicketRepoLocal tclid
|
|
guard $ ticketRepoLocalRepo trl == rid
|
|
bnids <-
|
|
MaybeT $
|
|
nonEmpty <$> selectKeysList [BundleTicket ==. tid] [Desc BundleId]
|
|
author <-
|
|
requireEitherAlt
|
|
(do mtal <- lift $ getBy $ UniqueTicketAuthorLocal ltid
|
|
for mtal $ \ tal@(Entity talid _) -> do
|
|
tupid1 <- MaybeT $ getKeyBy $ UniqueTicketUnderProjectProject tclid
|
|
tup@(Entity tupid2 _) <- MaybeT $ getBy $ UniqueTicketUnderProjectAuthor talid
|
|
unless (tupid1 == tupid2) $
|
|
error "TAL and TPL used by different TUPs!"
|
|
return (tal, tup)
|
|
)
|
|
(lift $ getBy $ UniqueTicketAuthorRemote tclid)
|
|
"MR doesn't have author"
|
|
"MR has both local and remote author"
|
|
mresolved <- lift $ getResolved ltid
|
|
return (es, er, Entity tid t, Entity ltid lt, etcl, etrl, author, mresolved, bnids)
|
|
|
|
getRepoProposal404
|
|
:: ShrIdent
|
|
-> RpIdent
|
|
-> KeyHashid LocalTicket
|
|
-> AppDB
|
|
( Entity Sharer
|
|
, Entity Repo
|
|
, Entity Ticket
|
|
, Entity LocalTicket
|
|
, Entity TicketContextLocal
|
|
, Entity TicketRepoLocal
|
|
, Either
|
|
(Entity TicketAuthorLocal, Entity TicketUnderProject)
|
|
(Entity TicketAuthorRemote)
|
|
, Maybe
|
|
( Entity TicketResolve
|
|
, Either
|
|
(Entity TicketResolveLocal)
|
|
(Entity TicketResolveRemote)
|
|
)
|
|
, NonEmpty BundleId
|
|
)
|
|
getRepoProposal404 shr rp ltkhid = do
|
|
ltid <- decodeKeyHashid404 ltkhid
|
|
mpatch <- getRepoProposal shr rp ltid
|
|
case mpatch of
|
|
Nothing -> notFound
|
|
Just patch -> return patch
|