@@ -21,12 +21,13 @@ import Data.Either (lefts, rights, isRight)
2121
2222-- | Record a lookup for a specific transaction in the graph.
2323data TransactionIdLookup = TransactionIdLookup TransactionId |
24− TransactionIdHeadNameLookup HeadName
24+ TransactionIdHeadNameLookup HeadName [TransactionIdHeadBacktrack]
2525 deriving (Show, Eq, Binary, Generic)
2626
2727-- topic~3^2
28−data TransactionIdHeadBacktrack = TransactionIdHeadParentBackTrack Int | -- git ~: walk back n parents, arbitrarily choosing a parent when a choice must be made
29− TransactionIdHeadBranchBackTrack Int -- git ^: walk back one parent level to the nth arbitrarily-chosen parent
28+data TransactionIdHeadBacktrack = TransactionIdHeadParentBacktrack Int | -- git ~: walk back n parents, arbitrarily choosing a parent when a choice must be made
29+ TransactionIdHeadBranchBacktrack Int -- git ^: walk back one parent level to the nth arbitrarily-chosen parent
30+ deriving (Show, Eq, Binary, Generic)
3031
3132--operators which manipulate a transaction graph
3233data TransactionGraphOperator = JumpToHead HeadName |
@@ -422,6 +423,36 @@ createUnionMergeTransaction newId strategy graph (t1,t2) = do
422423
423424lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
424425lookupTransaction graph (TransactionIdLookup tid) = transactionForId tid graph
425−lookupTransaction graph (TransactionIdHeadNameLookup headName) = case transactionForHead headName graph of
426− Just t -> Right t
427− Nothing -> Left (NoSuchHeadNameError headName)
426+lookupTransaction graph (TransactionIdHeadNameLookup headName backtracks) = case transactionForHead headName graph of
427+ Nothing -> Left (NoSuchHeadNameError headName)
428+ Just headTrans -> do
429+ traversedId <- traverseGraph graph (transactionId headTrans) backtracks
430+ transactionForId traversedId graph
431+
432+traverseGraph :: TransactionGraph -> TransactionId -> [TransactionIdHeadBacktrack] -> Either RelationalError TransactionId
433+traverseGraph graph currentTid backtrackSteps = foldM (backtrackGraph graph) currentTid backtrackSteps
434+
435+backtrackGraph :: TransactionGraph -> TransactionId -> TransactionIdHeadBacktrack -> Either RelationalError TransactionId
436+-- tilde, step back one parent link- if a choice must be made, choose the "first" link arbitrarily
437+backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
438+ trans <- transactionForId currentTid graph
439+ let parents = S.toAscList (transactionParentIds trans)
440+ if length parents < 1 then
441+ Left RootTransactionTraversalError
442+ else do
443+ parentTrans <- transactionForId (head parents) graph
444+ if steps == 1 then do
445+ pure (transactionId parentTrans)
446+ else
447+ backtrackGraph graph (transactionId parentTrans) (TransactionIdHeadParentBacktrack (steps - 1))
448+
449+backtrackGraph graph currentTid (TransactionIdHeadBranchBacktrack steps) = do
450+ trans <- transactionForId currentTid graph
451+ let parents = transactionParentIds trans
452+ if S.size parents < 1 then
453+ Left RootTransactionTraversalError
454+ else if S.size parents < steps then
455+ Left (ParentCountTraversalError (S.size parents) steps)
456+ else
457+ pure (S.elemAt (steps - 1) parents)
458+