read fetch from git and decode an Entity at an arbitrary git reference.
(def Definition, wrapper func(e *Entity) EntityT, repo repository.ClockedRepo, resolvers entity.Resolvers, ref string)
| 82 | |
| 83 | // read fetch from git and decode an Entity at an arbitrary git reference. |
| 84 | func read[EntityT entity.Interface](def Definition, wrapper func(e *Entity) EntityT, repo repository.ClockedRepo, resolvers entity.Resolvers, ref string) (EntityT, error) { |
| 85 | rootHash, err := repo.ResolveRef(ref) |
| 86 | if err == repository.ErrNotFound { |
| 87 | return *new(EntityT), entity.NewErrNotFound(def.Typename) |
| 88 | } |
| 89 | if err != nil { |
| 90 | return *new(EntityT), err |
| 91 | } |
| 92 | |
| 93 | // Perform a breadth-first search to get a topological order of the DAG where we discover the |
| 94 | // parents commit and go back in time up to the chronological root |
| 95 | |
| 96 | queue := make([]repository.Hash, 0, 32) |
| 97 | visited := make(map[repository.Hash]struct{}) |
| 98 | BFSOrder := make([]repository.Commit, 0, 32) |
| 99 | |
| 100 | queue = append(queue, rootHash) |
| 101 | visited[rootHash] = struct{}{} |
| 102 | |
| 103 | for len(queue) > 0 { |
| 104 | // pop |
| 105 | hash := queue[0] |
| 106 | queue = queue[1:] |
| 107 | |
| 108 | commit, err := repo.ReadCommit(hash) |
| 109 | if err != nil { |
| 110 | return *new(EntityT), err |
| 111 | } |
| 112 | |
| 113 | BFSOrder = append(BFSOrder, commit) |
| 114 | |
| 115 | for _, parent := range commit.Parents { |
| 116 | if _, ok := visited[parent]; !ok { |
| 117 | queue = append(queue, parent) |
| 118 | // mark as visited |
| 119 | visited[parent] = struct{}{} |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | // Now, we can reverse this topological order and read the commits in an order where |
| 125 | // we are sure to have read all the chronological ancestors when we read a commit. |
| 126 | |
| 127 | // Next step is to: |
| 128 | // 1) read the operationPacks |
| 129 | // 2) make sure that clocks causality respect the DAG topology. |
| 130 | |
| 131 | oppMap := make(map[repository.Hash]*operationPack) |
| 132 | var opsCount int |
| 133 | |
| 134 | for i := len(BFSOrder) - 1; i >= 0; i-- { |
| 135 | commit := BFSOrder[i] |
| 136 | isFirstCommit := i == len(BFSOrder)-1 |
| 137 | isMerge := len(commit.Parents) > 1 |
| 138 | |
| 139 | // Verify DAG structure: single chronological root, so only the root |
| 140 | // can have no parents. Said otherwise, the DAG need to have exactly |
| 141 | // one leaf. |
nothing calls this directly
no test coverage detected