Documentation ¶
Overview ¶
Package dag contains the base common code to define an entity stored in a chain of git objects, supporting actions like Push, Pull and Merge.
Index ¶
- func ClockLoader(defs ...Definition) repository.ClockLoader
- func Fetch(def Definition, repo repository.Repo, remote string) (string, error)
- func ListLocalIds(def Definition, repo repository.RepoData) ([]entity.Id, error)
- func MergeAll(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, ...) <-chan entity.MergeResult
- func Pull(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, ...) error
- func Push(def Definition, repo repository.Repo, remote string) (string, error)
- func ReadAll(def Definition, repo repository.ClockedRepo, resolver identity.Resolver) <-chan StreamedEntity
- func Remove(def Definition, repo repository.ClockedRepo, id entity.Id) error
- type Definition
- type Entity
- func (e *Entity) Append(op Operation)
- func (e *Entity) Commit(repo repository.ClockedRepo) error
- func (e *Entity) CommitAsNeeded(repo repository.ClockedRepo) error
- func (e *Entity) CreateLamportTime() lamport.Time
- func (e *Entity) EditLamportTime() lamport.Time
- func (e *Entity) FirstOp() Operation
- func (e *Entity) Id() entity.Id
- func (e *Entity) LastOp() Operation
- func (e *Entity) NeedCommit() bool
- func (e *Entity) Operations() []Operation
- func (e *Entity) Validate() error
- type Operation
- type OperationWithFiles
- type PGPKeyring
- type StreamedEntity
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClockLoader ¶
func ClockLoader(defs ...Definition) repository.ClockLoader
ClockLoader is the repository.ClockLoader for Entity
func Fetch ¶
func Fetch(def Definition, repo repository.Repo, remote string) (string, error)
Fetch retrieve updates from a remote This does not change the local entity state
func ListLocalIds ¶
func ListLocalIds(def Definition, repo repository.RepoData) ([]entity.Id, error)
ListLocalIds list all the available local Entity's Id
func MergeAll ¶
func MergeAll(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, remote string, author identity.Interface) <-chan entity.MergeResult
MergeAll will merge all the available remote Entity:
Multiple scenario exist:
- if the remote Entity doesn't exist locally, it's created --> emit entity.MergeStatusNew
- if the remote and local Entity have the same state, nothing is changed --> emit entity.MergeStatusNothing
- if the local Entity has new commits but the remote don't, nothing is changed --> emit entity.MergeStatusNothing
- if the remote has new commit, the local bug is updated to match the same history (fast-forward update) --> emit entity.MergeStatusUpdated
- if both local and remote Entity have new commits (that is, we have a concurrent edition), a merge commit with an empty operationPack is created to join both branch and form a DAG. --> emit entity.MergeStatusUpdated
Note: an author is necessary for the case where a merge commit is created, as this commit will have an author and may be signed if a signing key is available.
func Pull ¶
func Pull(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, remote string, author identity.Interface) error
Pull will do a Fetch + MergeAll Contrary to MergeAll, this function will return an error if a merge fail.
func Push ¶
func Push(def Definition, repo repository.Repo, remote string) (string, error)
Push update a remote with the local changes
func ReadAll ¶
func ReadAll(def Definition, repo repository.ClockedRepo, resolver identity.Resolver) <-chan StreamedEntity
ReadAll read and parse all local Entity
func Remove ¶
func Remove(def Definition, repo repository.ClockedRepo, id entity.Id) error
Remove delete an Entity. Remove is idempotent.
Types ¶
type Definition ¶
type Definition struct { // the name of the entity (bug, pull-request, ...), for human consumption Typename string // the Namespace in git references (bugs, prs, ...) Namespace string // a function decoding a JSON message into an Operation OperationUnmarshaler func(author identity.Interface, raw json.RawMessage, resolver identity.Resolver) (Operation, error) // the expected format version number, that can be used for data migration/upgrade FormatVersion uint }
Definition hold the details defining one specialization of an Entity.
type Entity ¶
type Entity struct { Definition // contains filtered or unexported fields }
Entity is a data structure stored in a chain of git objects, supporting actions like Push, Pull and Merge.
func Read ¶
func Read(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, id entity.Id) (*Entity, error)
Read will read and decode a stored local Entity from a repository
func (*Entity) Commit ¶
func (e *Entity) Commit(repo repository.ClockedRepo) error
Commit write the appended operations in the repository
func (*Entity) CommitAsNeeded ¶
func (e *Entity) CommitAsNeeded(repo repository.ClockedRepo) error
CommitAsNeeded execute a Commit only if necessary. This function is useful to avoid getting an error if the Entity is already in sync with the repository.
func (*Entity) CreateLamportTime ¶
CreateLamportTime return the Lamport time of creation
func (*Entity) EditLamportTime ¶
EditLamportTime return the Lamport time of the last edition
func (*Entity) NeedCommit ¶
NeedCommit indicate if the in-memory state changed and need to be commit in the repository
func (*Entity) Operations ¶
Operations return the ordered operations
type Operation ¶
type Operation interface { // Id return the Operation identifier // // Some care need to be taken to define a correct Id derivation and enough entropy in the data used to avoid // collisions. Notably: // - the Id of the first Operation will be used as the Id of the Entity. Collision need to be avoided across entities // of the same type (example: no collision within the "bug" namespace). // - collisions can also happen within the set of Operations of an Entity. Simple Operation might not have enough // entropy to yield unique Ids (example: two "close" operation within the same second, same author). // If this is a concern, it is recommended to include a piece of random data in the operation's data, to guarantee // a minimal amount of entropy and avoid collision. // // Author's note: I tried to find a clever way around that inelegance (stuffing random useless data into the stored // structure is not exactly elegant) but I failed to find a proper way. Essentially, anything that would reuse some // other data (parent operation's Id, lamport clock) or the graph structure (depth) impose that the Id would only // make sense in the context of the graph and yield some deep coupling between Entity and Operation. This in turn // make the whole thing even less elegant. // // A common way to derive an Id will be to use the entity.DeriveId() function on the serialized operation data. Id() entity.Id // Validate check if the Operation data is valid Validate() error // Author returns the author of this operation Author() identity.Interface }
Operation is a piece of data defining a change to reflect on the state of an Entity. What this Operation or Entity's state looks like is not of the resort of this package as it only deals with the data structure and storage.
type OperationWithFiles ¶
type OperationWithFiles interface { Operation // GetFiles return the files needed by this operation // This implies that the Operation maintain and store internally the references to those files. This is how // this information is read later, when loading from storage. // For example, an operation that has a text value referencing some files would maintain a mapping (text ref --> // hash). GetFiles() []repository.Hash }
OperationWithFiles is an extended Operation that has files dependency, stored in git.
type PGPKeyring ¶
PGPKeyring implement a openpgp.KeyRing from an slice of Key
func (PGPKeyring) DecryptionKeys ¶
func (pk PGPKeyring) DecryptionKeys() []openpgp.Key
func (PGPKeyring) KeysByIdUsage ¶
func (pk PGPKeyring) KeysByIdUsage(id uint64, requiredUsage byte) []openpgp.Key