Skip to content

Commit

Permalink
feat(base): defining base package
Browse files Browse the repository at this point in the history
For a while now we've wanted to carve a "local" package out of actions
that both p2p and actions can use. (Okay, we might get right of actions entirely,
I'm not sure yet). This starts that process, and already it's feelin' like a great
move.

I want to call it "base" instead of "core" b/c IPFS already has very developed
terminology around the word "core".
  • Loading branch information
b5 committed Oct 25, 2018
1 parent af3f854 commit 1a7cd42
Show file tree
Hide file tree
Showing 33 changed files with 721 additions and 356 deletions.
47 changes: 8 additions & 39 deletions actions/dataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/qri-io/dataset/detect"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/dataset/validate"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/repo/profile"
Expand Down Expand Up @@ -52,7 +53,7 @@ func NewDataset(dsp *dataset.DatasetPod) (ds *dataset.Dataset, body cafs.File, s
}

// open a data file if we can
if body, err = repo.DatasetPodBodyFile(dsp); err == nil {
if body, err = base.DatasetPodBodyFile(dsp); err == nil {
// defer body.Close()

// validate / generate dataset name
Expand Down Expand Up @@ -146,7 +147,7 @@ func UpdateDataset(node *p2p.QriNode, dsp *dataset.DatasetPod) (ds *dataset.Data
}

if dsp.BodyBytes != nil || dsp.BodyPath != "" {
if body, err = repo.DatasetPodBodyFile(dsp); err != nil {
if body, err = base.DatasetPodBodyFile(dsp); err != nil {
return
}
} else {
Expand Down Expand Up @@ -277,7 +278,7 @@ func SaveDataset(node *p2p.QriNode, name string, ds *dataset.Dataset, data cafs.
ds.Assign(userSet)
}

if err = PrepareViz(ds); err != nil {
if err = base.PrepareViz(ds); err != nil {
return
}

Expand All @@ -290,7 +291,7 @@ func SaveDataset(node *p2p.QriNode, name string, ds *dataset.Dataset, data cafs.
// memRepo should be able to wrap another repo & check that before returning not found
}

if ref, err = repo.CreateDataset(r, name, ds, data, pin); err != nil {
if ref, err = base.CreateDataset(r, name, ds, data, pin); err != nil {
return
}

Expand All @@ -303,7 +304,7 @@ func SaveDataset(node *p2p.QriNode, name string, ds *dataset.Dataset, data cafs.
r.LogEvent(repo.ETDsPinned, ref)
}

if err = ReadDataset(r, &ref); err != nil {
if err = base.ReadDataset(r, &ref); err != nil {
return
}

Expand Down Expand Up @@ -347,7 +348,7 @@ func AddDataset(node *p2p.QriNode, ref *repo.DatasetRef) (err error) {
return fmt.Errorf("error fetching file: %s", err.Error())
}

if err = PinDataset(r, *ref); err != nil {
if err = base.PinDataset(r, *ref); err != nil {
log.Debug(err.Error())
return fmt.Errorf("error pinning root key: %s", err.Error())
}
Expand All @@ -367,20 +368,6 @@ func AddDataset(node *p2p.QriNode, ref *repo.DatasetRef) (err error) {
return
}

// ReadDataset grabs a dataset from the store
func ReadDataset(r repo.Repo, ref *repo.DatasetRef) (err error) {
if store := r.Store(); store != nil {
ds, e := dsfs.LoadDataset(store, datastore.NewKey(ref.Path))
if e != nil {
return e
}
ref.Dataset = ds.Encode()
return
}

return datastore.ErrNotFound
}

// RenameDataset alters a dataset name
func RenameDataset(node *p2p.QriNode, current, new *repo.DatasetRef) (err error) {
r := node.Repo
Expand Down Expand Up @@ -410,24 +397,6 @@ func RenameDataset(node *p2p.QriNode, current, new *repo.DatasetRef) (err error)
return r.LogEvent(repo.ETDsRenamed, *new)
}

// PinDataset marks a dataset for retention in a store
func PinDataset(r repo.Repo, ref repo.DatasetRef) error {
if pinner, ok := r.Store().(cafs.Pinner); ok {
pinner.Pin(datastore.NewKey(ref.Path), true)
return r.LogEvent(repo.ETDsPinned, ref)
}
return repo.ErrNotPinner
}

// UnpinDataset unmarks a dataset for retention in a store
func UnpinDataset(r repo.Repo, ref repo.DatasetRef) error {
if pinner, ok := r.Store().(cafs.Pinner); ok {
pinner.Unpin(datastore.NewKey(ref.Path), true)
return r.LogEvent(repo.ETDsUnpinned, ref)
}
return repo.ErrNotPinner
}

// DeleteDataset removes a dataset from the store
func DeleteDataset(node *p2p.QriNode, ref *repo.DatasetRef) (err error) {
r := node.Repo
Expand Down Expand Up @@ -455,7 +424,7 @@ func DeleteDataset(node *p2p.QriNode, ref *repo.DatasetRef) (err error) {
return err
}

if err = UnpinDataset(r, *ref); err != nil && err != repo.ErrNotPinner {
if err = base.UnpinDataset(r, *ref); err != nil && err != repo.ErrNotPinner {
return err
}

Expand Down
3 changes: 2 additions & 1 deletion actions/dataset_head.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package actions
import (
"fmt"

"github.com/qri-io/qri/base"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
)
Expand All @@ -22,5 +23,5 @@ func DatasetHead(node *p2p.QriNode, ds *repo.DatasetRef) error {
return node.RequestDataset(ds)
}

return ReadDataset(node.Repo, ds)
return base.ReadDataset(node.Repo, ds)
}
48 changes: 4 additions & 44 deletions actions/dataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/qri-io/cafs"
"github.com/qri-io/dataset/dstest"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/config"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/p2p/test"
Expand Down Expand Up @@ -132,7 +133,6 @@ func DatasetTests(t *testing.T, rmf RepoMakerFunc) {
testSaveDataset,
testReadDataset,
testRenameDataset,
testDatasetPinning,
testDeleteDataset,
testEventsLog,
} {
Expand Down Expand Up @@ -170,7 +170,7 @@ func createDataset(t *testing.T, rmf RepoMakerFunc) (*p2p.QriNode, repo.DatasetR
func testReadDataset(t *testing.T, rmf RepoMakerFunc) {
n, ref := createDataset(t, rmf)

if err := ReadDataset(n.Repo, &ref); err != nil {
if err := base.ReadDataset(n.Repo, &ref); err != nil {
t.Error(err.Error())
return
}
Expand All @@ -194,7 +194,7 @@ func testRenameDataset(t *testing.T, rmf RepoMakerFunc) {
return
}

if err := ReadDataset(node.Repo, b); err != nil {
if err := base.ReadDataset(node.Repo, b); err != nil {
t.Error(err.Error())
return
}
Expand All @@ -205,46 +205,6 @@ func testRenameDataset(t *testing.T, rmf RepoMakerFunc) {
}
}

func testDatasetPinning(t *testing.T, rmf RepoMakerFunc) {
node, ref := createDataset(t, rmf)

if err := PinDataset(node.Repo, ref); err != nil {
if err == repo.ErrNotPinner {
t.Log("repo store doesn't support pinning")
} else {
t.Error(err.Error())
return
}
}

tc, err := dstest.NewTestCaseFromDir(testdataPath("counter"))
if err != nil {
t.Error(err.Error())
return
}

ref2, _, err := SaveDataset(node, tc.Name, tc.Input, tc.BodyFile(), nil, false, false)
if err != nil {
t.Error(err.Error())
return
}

if err := PinDataset(node.Repo, ref2); err != nil && err != repo.ErrNotPinner {
t.Error(err.Error())
return
}

if err := UnpinDataset(node.Repo, ref); err != nil && err != repo.ErrNotPinner {
t.Error(err.Error())
return
}

if err := UnpinDataset(node.Repo, ref2); err != nil && err != repo.ErrNotPinner {
t.Error(err.Error())
return
}
}

func testDeleteDataset(t *testing.T, rmf RepoMakerFunc) {
node, ref := createDataset(t, rmf)

Expand All @@ -268,7 +228,7 @@ func testEventsLog(t *testing.T, rmf RepoMakerFunc) {
return
}

if err := PinDataset(node.Repo, *b); err != nil {
if err := base.PinDataset(node.Repo, *b); err != nil {
if err == repo.ErrNotPinner {
pinner = false
} else {
Expand Down
29 changes: 2 additions & 27 deletions actions/list_datasets.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package actions
import (
"fmt"

"github.com/ipfs/go-datastore"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/repo/profile"
Expand Down Expand Up @@ -72,29 +71,5 @@ func ListDatasets(node *p2p.QriNode, ds *repo.DatasetRef, limit, offset int, RPC
return
}

store := r.Store()
res, err = r.References(limit, offset)
if err != nil {
log.Debug(err.Error())
return nil, fmt.Errorf("error getting dataset list: %s", err.Error())
}

renames := repo.NewNeedPeernameRenames()
for i, ref := range res {
// May need to change peername.
if err := repo.CanonicalizeProfile(r, &res[i], &renames); err != nil {
return nil, fmt.Errorf("error canonicalizing dataset peername: %s", err.Error())
}

ds, err := dsfs.LoadDataset(store, datastore.NewKey(ref.Path))
if err != nil {
return nil, fmt.Errorf("error loading path: %s, err: %s", ref.Path, err.Error())
}
res[i].Dataset = ds.Encode()
if RPC {
res[i].Dataset.Structure.Schema = nil
}
}
// TODO: If renames.Renames is non-empty, apply it to r
return
return base.ListDatasets(node.Repo, limit, offset, RPC)
}
26 changes: 2 additions & 24 deletions actions/log.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package actions

import (
"github.com/ipfs/go-datastore"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
)
Expand All @@ -18,26 +17,5 @@ func DatasetLog(node *p2p.QriNode, ref repo.DatasetRef, limit, offset int) (rlog
return node.RequestDatasetLog(ref, limit, offset)
}

for {
ds, e := dsfs.LoadDataset(node.Repo.Store(), datastore.NewKey(ref.Path))
if e != nil {
return nil, e
}
ref.Dataset = ds.Encode()

offset--
if offset > 0 {
continue
}

rlog = append(rlog, ref)

limit--
if limit == 0 || ref.Dataset.PreviousPath == "" {
break
}
ref.Path = ref.Dataset.PreviousPath
}

return rlog, nil
return base.DatasetLog(node.Repo, ref, limit, offset)
}
16 changes: 0 additions & 16 deletions actions/render_test.go

This file was deleted.

37 changes: 37 additions & 0 deletions base/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Package base defines business that operates on local data
// it's main job is to composing APIs from the lower half of our tech stack,
// providing uniform functions for higher up packages, mainly p2p and actions.
// p2p and actions should use base as the only way of operate on the local repo
// Here's some ascii art to clarify the stack:
//
// ┌───────────────┐ ┌───────────────┐
// │ cmd │ │ api │
// └───────────────┘ └───────────────┘
// ┌─────────────────────────────────┐
// │ lib │
// └─────────────────────────────────┘
// ┌─────────────────────────────────┐
// │ actions │
// └─────────────────────────────────┘
// ┌───────────────────────┐
// │ p2p │
// └───────────────────────┘
// ┌─────────────────────────────────┐
// │ base │ <-- you are here
// └─────────────────────────────────┘
// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
// │ repo │ │ dsfs │ │ cafs │ │ ... │
// └──────┘ └──────┘ └──────┘ └──────┘
//
// There are packages omitted from this diagram, but these are the vitals.
// base functions mainly work with repo.Repo instances, using repo interface methods
// and related packages to do their work. This is part of a larger pattern of
// having actions rely on lower level interfaces wherever possible to enhance
// configurability
package base

import (
golog "github.com/ipfs/go-log"
)

var log = golog.Logger("base")
Loading

0 comments on commit 1a7cd42

Please sign in to comment.