dag

package
v0.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2022 License: GPL-3.0 Imports: 12 Imported by: 0

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

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:

  1. if the remote Entity doesn't exist locally, it's created --> emit entity.MergeStatusNew
  2. if the remote and local Entity have the same state, nothing is changed --> emit entity.MergeStatusNothing
  3. if the local Entity has new commits but the remote don't, nothing is changed --> emit entity.MergeStatusNothing
  4. if the remote has new commit, the local bug is updated to match the same history (fast-forward update) --> emit entity.MergeStatusUpdated
  5. 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 New

func New(definition Definition) *Entity

New create an empty Entity

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) Append

func (e *Entity) Append(op Operation)

Append add a new Operation to the Entity

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

func (e *Entity) CreateLamportTime() lamport.Time

CreateLamportTime return the Lamport time of creation

func (*Entity) EditLamportTime

func (e *Entity) EditLamportTime() lamport.Time

EditLamportTime return the Lamport time of the last edition

func (*Entity) FirstOp

func (e *Entity) FirstOp() Operation

FirstOp lookup for the very first operation of the Entity

func (*Entity) Id

func (e *Entity) Id() entity.Id

Id return the Entity identifier

func (*Entity) LastOp

func (e *Entity) LastOp() Operation

LastOp lookup for the very last operation of the Entity

func (*Entity) NeedCommit

func (e *Entity) NeedCommit() bool

NeedCommit indicate if the in-memory state changed and need to be commit in the repository

func (*Entity) Operations

func (e *Entity) Operations() []Operation

Operations return the ordered operations

func (*Entity) Validate

func (e *Entity) Validate() error

Validate check if the Entity data is valid

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

type PGPKeyring []*identity.Key

PGPKeyring implement a openpgp.KeyRing from an slice of Key

func (PGPKeyring) DecryptionKeys

func (pk PGPKeyring) DecryptionKeys() []openpgp.Key

func (PGPKeyring) KeysById

func (pk PGPKeyring) KeysById(id uint64) []openpgp.Key

func (PGPKeyring) KeysByIdUsage

func (pk PGPKeyring) KeysByIdUsage(id uint64, requiredUsage byte) []openpgp.Key

type StreamedEntity

type StreamedEntity struct {
	Entity *Entity
	Err    error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL