Documentation ¶
Overview ¶
Package repo represents a repository of qri information Analogous to a git repository, repo expects a rigid structure filled with rich types specific to qri. Lots of things in here take inspiration from the ipfs datastore interface: github.com/ipfs/go-datastore
Index ¶
- Constants
- Variables
- func CanonicalizeDatasetRef(r Repo, ref *DatasetRef) error
- func CanonicalizePeername(r Repo, peername *string) error
- func CompareDatasetRef(a, b DatasetRef) error
- func DataNodes(nodes map[string]*dsgraph.Node) (ds map[string]bool)
- func DatasetForQuery(r Repo, qpath datastore.Key) (datastore.Key, error)
- func DatasetQueries(nodes map[string]*dsgraph.Node) (qs map[string]datastore.Key)
- func DatasetsQuery(dss Datasets, q query.Query) (map[string]*dataset.Dataset, error)
- func Graph(r Repo) (map[string]*dsgraph.Node, error)
- func HasPath(r Repo, path datastore.Key) (bool, error)
- func QueriesMap(nodes map[string]*dsgraph.Node) (qs map[string]datastore.Key)
- func QueryPeers(ps Peers, q query.Query) ([]*profile.Profile, error)
- func WalkRepoDatasets(r Repo, visit func(depth int, ref *DatasetRef, err error) (bool, error)) error
- type ChangeRequest
- type ChangeRequestStore
- type DatasetRef
- type Datasets
- type MemChangeRequests
- func (mcr MemChangeRequests) ChangeRequestsForTarget(target datastore.Key, limit, offset int) ([]*ChangeRequest, error)
- func (mcr MemChangeRequests) DeleteChangeRequest(path datastore.Key) error
- func (mcr MemChangeRequests) GetChangeRequest(path datastore.Key) (*ChangeRequest, error)
- func (mcr MemChangeRequests) ListChangeRequests(limit, offset int) ([]*ChangeRequest, error)
- func (mcr MemChangeRequests) PutChangeRequest(path datastore.Key, cr *ChangeRequest) error
- type MemDatasets
- func (d MemDatasets) DeleteDataset(path datastore.Key) error
- func (d MemDatasets) GetDataset(path datastore.Key) (*dataset.Dataset, error)
- func (d MemDatasets) PutDataset(path datastore.Key, ds *dataset.Dataset) error
- func (d MemDatasets) PutDatasets(datasets []*DatasetRef) error
- func (d MemDatasets) Query(q query.Query) (query.Results, error)
- type MemPeers
- func (m MemPeers) DeletePeer(id peer.ID) error
- func (m MemPeers) GetID(peername string) (peer.ID, error)
- func (m MemPeers) GetPeer(id peer.ID) (*profile.Profile, error)
- func (m MemPeers) IPFSPeerID(peername string) (peer.ID, error)
- func (m MemPeers) List() (map[string]*profile.Profile, error)
- func (m MemPeers) PutPeer(id peer.ID, profile *profile.Profile) error
- func (m MemPeers) Query(q query.Query) (query.Results, error)
- type MemQueryLog
- type MemRefstore
- type MemRepo
- func (r *MemRepo) Analytics() analytics.Analytics
- func (r *MemRepo) Cache() Datasets
- func (r *MemRepo) CreateDataset(ds *dataset.Dataset, data cafs.File, pin bool) (path datastore.Key, err error)
- func (r *MemRepo) Graph() (map[string]*dsgraph.Node, error)
- func (r *MemRepo) Peers() Peers
- func (r *MemRepo) Profile() (*profile.Profile, error)
- func (r *MemRepo) SaveProfile(p *profile.Profile) error
- func (r *MemRepo) SetPrivateKey(pk crypto.PrivKey) error
- func (r *MemRepo) Store() cafs.Filestore
- type NodeList
- type Peers
- type QueryLog
- type QueryLogItem
- type Refstore
- type Repo
- type SearchParams
- type Searchable
Constants ¶
const ( // ChangeRequestStatusOpen is a request that hasn't been addressed yet ChangeRequestStatusOpen = "open" // ChangeRequestStatusAccepted have been merged into // the target history ChangeRequestStatusAccepted = "accepted" // ChangeRequestStatusDeclined will not be merged into // the target history ChangeRequestStatusDeclined = "declined" )
Variables ¶
var ( // ErrNotFound is the err implementers should return when stuff isn't found ErrNotFound = fmt.Errorf("repo: not found") // ErrPeernameRequired is for when a peername is missing-but-expected ErrPeernameRequired = fmt.Errorf("repo: peername is required") // ErrNameRequired is for when a name is missing-but-expected ErrNameRequired = fmt.Errorf("repo: name is required") // ErrPathRequired is for when a path is missing-but-expected ErrPathRequired = fmt.Errorf("repo: path is required") // ErrNameTaken is for when a name name is already taken ErrNameTaken = fmt.Errorf("repo: name already in use") // ErrRepoEmpty is for when the repo has no datasets ErrRepoEmpty = fmt.Errorf("repo: this repo contains no datasets") )
Functions ¶
func CanonicalizeDatasetRef ¶ added in v0.1.1
func CanonicalizeDatasetRef(r Repo, ref *DatasetRef) error
CanonicalizeDatasetRef uses a repo to turn any local aliases into known canonical peername for a dataset and populates a missing path if the repo has path information for a peername/name combo if we provide any other shortcuts for names other than "me" in the future, it should be handled here.
func CanonicalizePeername ¶ added in v0.1.1
CanonicalizePeername uses a repo to replace aliases with canonical peernames. basically, this thing replaces "me" with the proper peername.
func CompareDatasetRef ¶
func CompareDatasetRef(a, b DatasetRef) error
CompareDatasetRef compares two Dataset References, returning an error describing any difference between the two references
func DatasetForQuery ¶
DatasetForQuery gives a corresponding dataset for a query path if one exists
func DatasetQueries ¶
DatasetQueries returns a mapped subset of a list of nodes in the form:
DatasetHash : QueryHash
func DatasetsQuery ¶
DatasetsQuery is a convenience function to read all query results & parse into a map[string]*dataset.Dataset.
func Graph ¶
Graph generates a map of all paths on this repository pointing to dsgraph.Node structs with all links configured. This is potentially expensive to calculate. Best to do some caching.
func QueriesMap ¶
QueriesMap returns a mapped subset of a list of nodes in the form:
QueryHash : DatasetHash
func QueryPeers ¶
QueryPeers wraps a call to Query, transforming responses to a slice of Profile pointers
func WalkRepoDatasets ¶
func WalkRepoDatasets(r Repo, visit func(depth int, ref *DatasetRef, err error) (bool, error)) error
WalkRepoDatasets visits every dataset in the history of a user's namespace Yes, this potentially a very expensive function to call, use sparingly.
Types ¶
type ChangeRequest ¶
type ChangeRequest struct { // status of this request. one of: open,accepted,declined Status string `json:"status"` // created marks the time this change request was created Created time.Time `json:"created"` // the dataset this change is aimed at. The // history of target must match the history // of change up until new history entries // TODO - should changes be targeting a mutable history? Target datastore.Key `json:"target"` // path to HEAD of the change history Path datastore.Key `json:"path"` // The actual change history. All relevant details must be stored // in the dataset itself. Title & description of the change goes // into this dataset's commit. Change *dataset.Dataset `json:"change"` }
ChangeRequest is one or more proposed additions to the history of a given dataset
type ChangeRequestStore ¶
type ChangeRequestStore interface { // Put a change request into the store PutChangeRequest(path datastore.Key, cr *ChangeRequest) error // Get a change request by it's path GetChangeRequest(path datastore.Key) (*ChangeRequest, error) // accept an open change request // AcceptChangeRequest(path datastore.Key) error // decline an open change request // DeclineChangeRequest(path datastore.Key) error // get change requests for a given target ChangeRequestsForTarget(target datastore.Key, limit, offset int) ([]*ChangeRequest, error) // list change requests in this store ListChangeRequests(limit, offset int) ([]*ChangeRequest, error) }
ChangeRequestStore is the interface for storying & manipulating Change Requests Qri repos should embed a ChangeRequestStore
type DatasetRef ¶
type DatasetRef struct { // Peername of dataset owner Peername string `json:"peername,omitempty"` // Unique name reference for this dataset Name string `json:"name,omitempty"` // Content-addressed path for this dataset Path string `json:"path,omitempty"` // Dataset is a pointer to the dataset being referenced Dataset *dataset.Dataset `json:"dataset,omitempty"` }
DatasetRef encapsulates a reference to a dataset. This needs to exist to bind ways of referring to a dataset to a dataset itself, as datasets can't easily contain their own hash information, and names are unique on a per-repository basis. It's tempting to think this needs to be "bigger", supporting more fields, keep in mind that if the information is important at all, it should be stored as metadata within the dataset itself.
func ParseDatasetRef ¶
func ParseDatasetRef(ref string) (DatasetRef, error)
ParseDatasetRef decodes a dataset reference from a string value It’s possible to refer to a dataset in a number of ways. The full definition of a dataset reference is as follows:
dataset_reference = peer_name/dataset_name@/network/hash
we swap in defaults as follows, all of which are represented as empty strings:
network - defaults to /ipfs/ hash - tip of version history (latest known commit)
these defaults are currently enforced by convention. TODO - make Dataset Ref parsing the responisiblity of the Repo interface, replacing empty strings with actual defaults
through defaults the following should all parse:
peer_name/dataset_name dataset_name@hash /network/hash peername hash
see tests for more exmples
dataset names & hashes are disambiguated by checking if the input parses to a valid multihash after base58 decoding
TODO - add validation that prevents peernames from being valid base58 multihashes. TODO - figure out how IPFS CID's play into this
func (DatasetRef) Equal ¶ added in v0.1.1
func (r DatasetRef) Equal(b DatasetRef) bool
Equal returns true only if Peername Name and Path are equal
func (DatasetRef) IsEmpty ¶ added in v0.1.1
func (r DatasetRef) IsEmpty() bool
IsEmpty returns true if none of it's fields are set
func (DatasetRef) IsPeerRef ¶
func (r DatasetRef) IsPeerRef() bool
IsPeerRef returns true if only Peername is set
func (DatasetRef) Match ¶ added in v0.1.1
func (r DatasetRef) Match(b DatasetRef) bool
Match checks returns true if Peername and Name are equal, and/or path is equal
func (DatasetRef) String ¶
func (r DatasetRef) String() (s string)
String implements the Stringer interface for DatasetRef
type Datasets ¶
type Datasets interface { // Put a dataset in the store PutDataset(path datastore.Key, ds *dataset.Dataset) error // Put multiple datasets in the store PutDatasets([]*DatasetRef) error // Get a dataset from the store GetDataset(path datastore.Key) (*dataset.Dataset, error) // Remove a dataset from the store DeleteDataset(path datastore.Key) error // Query is extracted from the ipfs datastore interface: Query(query.Query) (query.Results, error) }
Datasets is the minimum interface to act as a store of datasets. It's intended to look a *lot* like the ipfs datastore interface, but scoped only to datasets to make for easier consumption. Datasets stored here should be reasonably dereferenced to avoid additional lookups. All fields here work only with paths (which are datastore.Key's) to dereference a name, you'll need a Refstore interface oh golang, can we haz generics plz?
type MemChangeRequests ¶
type MemChangeRequests map[string]*ChangeRequest
MemChangeRequests is an in-memory map of change requests
func (MemChangeRequests) ChangeRequestsForTarget ¶
func (mcr MemChangeRequests) ChangeRequestsForTarget(target datastore.Key, limit, offset int) ([]*ChangeRequest, error)
ChangeRequestsForTarget get change requests for a given ("target") dataset
func (MemChangeRequests) DeleteChangeRequest ¶
func (mcr MemChangeRequests) DeleteChangeRequest(path datastore.Key) error
DeleteChangeRequest removes a change requres from the store by it's path
func (MemChangeRequests) GetChangeRequest ¶
func (mcr MemChangeRequests) GetChangeRequest(path datastore.Key) (*ChangeRequest, error)
GetChangeRequest fetches a change request by it's path
func (MemChangeRequests) ListChangeRequests ¶
func (mcr MemChangeRequests) ListChangeRequests(limit, offset int) ([]*ChangeRequest, error)
ListChangeRequests enumerates change requests in this store
func (MemChangeRequests) PutChangeRequest ¶
func (mcr MemChangeRequests) PutChangeRequest(path datastore.Key, cr *ChangeRequest) error
PutChangeRequest adds a change request to the store
type MemDatasets ¶
type MemDatasets struct {
// contains filtered or unexported fields
}
MemDatasets is an in-memory implementation of the DatasetStore interface
func NewMemDatasets ¶
func NewMemDatasets(store cafs.Filestore) MemDatasets
NewMemDatasets creates a datasets instance from a cafs.Filstore
func (MemDatasets) DeleteDataset ¶
func (d MemDatasets) DeleteDataset(path datastore.Key) error
DeleteDataset removes a dataset from the store
func (MemDatasets) GetDataset ¶
func (d MemDatasets) GetDataset(path datastore.Key) (*dataset.Dataset, error)
GetDataset fetches a dataset from the store
func (MemDatasets) PutDataset ¶
func (d MemDatasets) PutDataset(path datastore.Key, ds *dataset.Dataset) error
PutDataset adds a dataset to the store, referenced by a given key
func (MemDatasets) PutDatasets ¶
func (d MemDatasets) PutDatasets(datasets []*DatasetRef) error
PutDatasets adds multiple dataset references to the store
type MemPeers ¶
MemPeers is an in-memory implementation of the Peers interface
func (MemPeers) DeletePeer ¶
DeletePeer removes a peer from this store
func (MemPeers) IPFSPeerID ¶
IPFSPeerID gives the IPFS peer.ID for a given peername
type MemQueryLog ¶
type MemQueryLog []*QueryLogItem
MemQueryLog is an in-memory implementation of the QueryLog interface
func (MemQueryLog) ListQueryLogs ¶
func (ql MemQueryLog) ListQueryLogs(limit, offset int) ([]*QueryLogItem, error)
ListQueryLogs grabs a set of QueryLogItems from the store
func (*MemQueryLog) LogQuery ¶
func (ql *MemQueryLog) LogQuery(item *QueryLogItem) error
LogQuery adds a query entry to the store
func (*MemQueryLog) QueryLogItem ¶
func (ql *MemQueryLog) QueryLogItem(q *QueryLogItem) (*QueryLogItem, error)
QueryLogItem fills a partial QueryLogItem with all details from the store
type MemRefstore ¶ added in v0.1.1
type MemRefstore []DatasetRef
MemRefstore is an in-memory implementation of the Namestore interface
func (*MemRefstore) DeleteRef ¶ added in v0.1.1
func (r *MemRefstore) DeleteRef(del DatasetRef) error
DeleteRef removes a name from the store
func (MemRefstore) GetRef ¶ added in v0.1.1
func (r MemRefstore) GetRef(get DatasetRef) (ref DatasetRef, err error)
GetRef completes a reference with , refs can have either Path or Peername & Name specified, GetRef should fill out the missing pieces
func (*MemRefstore) PutRef ¶ added in v0.1.1
func (r *MemRefstore) PutRef(put DatasetRef) error
PutRef adds a reference to the namestore. Only complete references may be added
func (MemRefstore) RefCount ¶ added in v0.1.1
func (r MemRefstore) RefCount() (int, error)
RefCount returns the total number of names in the store
func (MemRefstore) References ¶ added in v0.1.1
func (r MemRefstore) References(limit, offset int) ([]DatasetRef, error)
References grabs a set of names from the Store's namespace
type MemRepo ¶
type MemRepo struct { MemDatasets *MemRefstore *MemQueryLog MemChangeRequests // contains filtered or unexported fields }
MemRepo is an in-memory implementation of the Repo interface
func (*MemRepo) CreateDataset ¶
func (r *MemRepo) CreateDataset(ds *dataset.Dataset, data cafs.File, pin bool) (path datastore.Key, err error)
CreateDataset initializes a dataset from a dataset pointer and data file
func (*MemRepo) SaveProfile ¶
SaveProfile updates this repo's profile
func (*MemRepo) SetPrivateKey ¶
SetPrivateKey sets this repos's internal private key reference
type Peers ¶
type Peers interface { List() (map[string]*profile.Profile, error) Query(query.Query) (query.Results, error) IPFSPeerID(peername string) (peer.ID, error) GetID(peername string) (peer.ID, error) PutPeer(id peer.ID, profile *profile.Profile) error GetPeer(id peer.ID) (*profile.Profile, error) DeletePeer(id peer.ID) error }
Peers is a store of peer information It's named peers to disambiguate from the lib-p2p peerstore
type QueryLog ¶
type QueryLog interface { LogQuery(*QueryLogItem) error ListQueryLogs(limit, offset int) ([]*QueryLogItem, error) QueryLogItem(q *QueryLogItem) (*QueryLogItem, error) }
QueryLog keeps logs
type QueryLogItem ¶
type QueryLogItem struct { Query string Name string Key datastore.Key DatasetPath datastore.Key Time time.Time }
QueryLogItem is a list of details for logging a query
type Refstore ¶ added in v0.1.1
type Refstore interface { // PutRef adds a reference to the store. References must be complete with // Peername, Name, and Path specified PutRef(ref DatasetRef) error GetRef(ref DatasetRef) (DatasetRef, error) DeleteRef(ref DatasetRef) error References(limit, offset int) ([]DatasetRef, error) RefCount() (int, error) }
Refstore keeps a collection of dataset references
type Repo ¶
type Repo interface { // All repositories wraps a content-addressed filestore as the cannonical // record of this repository's data. Store gives direct access to the // cafs.Filestore instance any given repo is using. Store() cafs.Filestore // Graph returns a graph of this repositories data resources Graph() (map[string]*dsgraph.Node, error) // All Repos must keep a Refstore, defining a given peer's datasets Refstore // CreateDataset initializes a dataset from a dataset pointer and data file // It's not part of the Datasets interface because creating a dataset requires // access to this repos store & private key CreateDataset(ds *dataset.Dataset, data cafs.File, pin bool) (path datastore.Key, err error) // Repos also serve as a store of dataset information. // It's important that this store maintain sync with any underlying filestore. // (which is why we might want to kill this in favor of just having a cache?) // The behaviour of the embedded DatasetStore will typically differ from the cache, // by only returning saved/pinned/permanent datasets. Datasets // QueryLog keeps a log of queries that have been run QueryLog // ChangeRequets gives this repo's change request store ChangeRequestStore // A repository must maintain profile information about the owner of this dataset. // The value returned by Profile() should represent the peer. Profile() (*profile.Profile, error) // It must be possible to alter profile information. SaveProfile(*profile.Profile) error // SetPrivateKey sets an internal reference to the private key for this profile. // PrivateKey is used to tie peer actions to this profile. Repo implementations must // never expose this private key once set. SetPrivateKey(pk crypto.PrivKey) error // A repository must maintain profile information about encountered peers. // Decsisions regarding retentaion of peers is left to the the implementation // TODO - should rename this to "profiles" to separate from the networking // concept of a peer Peers() Peers // Cache keeps an ephemeral store of dataset information // that may be purged at any moment. Results of searching for datasets, // dataset references other peers have, etc, should all be stored here. Cache() Datasets // All repositories provide their own analytics information. // Our analytics implementation is under super-active development. Analytics() analytics.Analytics }
Repo is the interface for working with a qri repository qri repos are stored graph of resources:datasets, known peers, analytics data, change requests, etc. Repos are connected to a single peer profile. Repos must wrap an underlying cafs.Filestore, which is intended to act as the canonical store of state across all peers that this repo may interact with.
type SearchParams ¶
SearchParams encapsulates parameters provided to Searchable.Search
type Searchable ¶
type Searchable interface {
Search(p SearchParams) ([]DatasetRef, error)
}
Searchable is an opt-in interface for supporting repository search