Skip to content

Commit

Permalink
feat(log): use logbook to show versions
Browse files Browse the repository at this point in the history
I'm too tired to write a good commit message. Sawwy
  • Loading branch information
b5 committed Oct 12, 2019
1 parent c3aea18 commit 1c38865
Show file tree
Hide file tree
Showing 17 changed files with 326 additions and 64 deletions.
20 changes: 17 additions & 3 deletions actions/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,29 @@ import (
)

// DatasetLog fetches the history of changes to a dataset
// TODO (b5) - implement remote log fetching
func DatasetLog(ctx context.Context, node *p2p.QriNode, ref repo.DatasetRef, limit, offset int) (rlog []repo.DatasetRef, err error) {
func DatasetLog(ctx context.Context, node *p2p.QriNode, ref repo.DatasetRef, limit, offset int) (rlog []base.DatasetLogItem, err error) {
local, err := ResolveDatasetRef(ctx, node, nil, "", &ref)
if err != nil {
return
}

if !local {
return node.RequestDatasetLog(ctx, ref, limit, offset)
res, err := node.RequestDatasetLog(ctx, ref, limit, offset)
if err != nil {
return nil, err
}
rlog = make([]base.DatasetLogItem, len(res))
for i, v := range res {
rlog[i] = base.DatasetLogItem{
Ref: repo.ConvertToDsref(v),
}
if v.Dataset != nil {
rlog[i].Timestamp = v.Dataset.Commit.Timestamp
rlog[i].CommitTitle = v.Dataset.Commit.Title
rlog[i].CommitMessage = v.Dataset.Commit.Message
}
}
return rlog, err
}

return base.DatasetLog(ctx, node.Repo, ref, limit, offset, true)
Expand Down
23 changes: 22 additions & 1 deletion actions/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import (
"context"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/config"
"github.com/qri-io/qri/dsref"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
testrepo "github.com/qri-io/qri/repo/test"
Expand All @@ -31,11 +35,28 @@ func TestDatasetLog(t *testing.T) {
}

ref = repo.MustParseDatasetRef("peer/movies")
if log, err = DatasetLog(ctx, node, ref, -1, 0); err != nil {
if log, err = DatasetLog(ctx, node, ref, 1, 0); err != nil {
t.Error(err.Error())
}
if len(log) != 1 {
t.Errorf("log length mismatch. expected: %d, got: %d", 1, len(log))
}

expect := []base.DatasetLogItem{
{
Ref: dsref.Ref{
Username: "peer",
Name: "movies",
ProfileID: "QmZePf5LeXow3RW5U1AgEiNbW46YnRGhZ7HPvm1UmPFPwt",
// TODO (b5) - use constant time to make timestamp & path comparable
Path: "/map/QmfDpSrzqrSM9PctPqDserHRTAaGHUjLLqzYrGEKawU4iN",
},
CommitTitle: "initial commit",
},
}

if diff := cmp.Diff(expect, log, cmpopts.IgnoreFields(base.DatasetLogItem{}, "Timestamp"), cmpopts.IgnoreFields(dsref.Ref{}, "Path")); diff != "" {
t.Errorf("result mismatch (-want +got):\n%s", diff)
}

}
2 changes: 1 addition & 1 deletion api/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (h *LogHandlers) logHandler(w http.ResponseWriter, r *http.Request) {
ListParams: lp,
}

res := []repo.DatasetRef{}
res := []lib.DatasetLogItem{}
if err := h.Log(params, &res); err != nil {
if err == repo.ErrNoHistory {
util.WriteErrResponse(w, http.StatusUnprocessableEntity, err)
Expand Down
4 changes: 2 additions & 2 deletions base/dataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import (
"github.com/qri-io/dataset/dsio"
"github.com/qri-io/ioes"
"github.com/qri-io/qfs"
"github.com/qri-io/qri/logbook"
"github.com/qri-io/qfs/cafs"
"github.com/qri-io/qri/logbook"
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/repo/profile"
)
Expand Down Expand Up @@ -157,7 +157,7 @@ func ListDatasets(ctx context.Context, r repo.Repo, term string, limit, offset i
}

if showVersions {
dsVersions, err := DatasetLog(ctx, r, ref, 0, 0, false)
dsVersions, err := DatasetLog(ctx, r, ref, 1000000, 0, false)
if err != nil {
return nil, err
}
Expand Down
69 changes: 63 additions & 6 deletions base/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,70 @@ import (

"github.com/qri-io/dataset"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/dsref"
"github.com/qri-io/qri/repo"
)

// DatasetLog fetches the history of changes to a dataset, if loadDatasets is true, dataset information will be populated
func DatasetLog(ctx context.Context, r repo.Repo, ref repo.DatasetRef, limit, offset int, loadDatasets bool) (rlog []repo.DatasetRef, err error) {
// DatasetLogItem is a line item in a dataset response
type DatasetLogItem struct {
Ref dsref.Ref `json:"ref,omitempty"`
// Creation timestamp
Timestamp time.Time `json:"timestamp,omitempty"`
// Title field from dataset.commit component
CommitTitle string `json:"commitTitle,omitempty"`
// Message field from dataset.commit component
CommitMessage string `json:"commitMessage,omitempty"`
Published bool `json:"published,omitempty"`
}

// DatasetLog fetches the change version history of a dataset
func DatasetLog(ctx context.Context, r repo.Repo, ref repo.DatasetRef, limit, offset int, loadDatasets bool) (items []DatasetLogItem, err error) {
if book := r.Logbook(); book != nil {
if versions, err := book.Versions(repo.ConvertToDsref(ref), offset, limit); err == nil {
items = make([]DatasetLogItem, len(versions))
// log is returned newest-first, fill slice in reverse
i := len(items) - 1
for _, v := range versions {
items[i] = DatasetLogItem{
Ref: v.Ref,
Published: v.Published,
Timestamp: v.Timestamp,
CommitTitle: v.CommitTitle,
}
i--
}
return items, nil
}
}

rlog, err := DatasetLogFromHistory(ctx, r, ref, offset, limit, loadDatasets)
if err != nil {
return nil, err
}
items = make([]DatasetLogItem, len(rlog))
for i, vref := range rlog {
items[i] = DatasetLogItem{Ref: repo.ConvertToDsref(vref)}
if vref.Dataset != nil {
items[i].Timestamp = vref.Dataset.Commit.Timestamp
items[i].CommitTitle = vref.Dataset.Commit.Title
items[i].CommitMessage = vref.Dataset.Commit.Message
}
}

// add a history entry b/c we didn't have one, but repo didn't error
go func() {
if err := ConstructDatasetLogFromHistory(context.Background(), r, repo.ConvertToDsref(ref)); err != nil {
log.Errorf("ConstructDatasetLogFromHistory: %s", err)
}
}()

return items, err
}

// DatasetLogFromHistory fetches the history of changes to a dataset by walking
// backwards through dataset commits. if loadDatasets is true, dataset
// information will be populated
func DatasetLogFromHistory(ctx context.Context, r repo.Repo, ref repo.DatasetRef, offset, limit int, loadDatasets bool) (rlog []repo.DatasetRef, err error) {
// TODO (b5) - this is a horrible hack to handle long-lived requests when connected to IPFS
// if we don't have the dataset locally, this process will take longer than 700 mill, because it'll
// reach out onto the d.web to attempt to resolve previous hashes. capping the duration
Expand All @@ -37,7 +95,6 @@ func DatasetLog(ctx context.Context, r repo.Repo, ref repo.DatasetRef, limit, of
ref.Dataset = ds

if offset <= 0 {
// rlog = append(rlog, ref)
versions <- ref

limit--
Expand Down Expand Up @@ -70,7 +127,7 @@ func DatasetLog(ctx context.Context, r repo.Repo, ref repo.DatasetRef, limit, of
// ConstructDatasetLogFromHistory constructs a log for a name if one doesn't
// exist.
func ConstructDatasetLogFromHistory(ctx context.Context, r repo.Repo, ref dsref.Ref) error {
refs, err := DatasetLog(ctx, r, repo.DatasetRef{ Peername: ref.Username, Name: ref.Name}, 1000000, 0, true)
refs, err := DatasetLogFromHistory(ctx, r, repo.DatasetRef{Peername: ref.Username, Name: ref.Name}, 0, 1000000, true)
if err != nil {
return err
}
Expand All @@ -81,4 +138,4 @@ func ConstructDatasetLogFromHistory(ctx context.Context, r repo.Repo, ref dsref.

book := r.Logbook()
return book.ConstructDatasetLog(ctx, ref, history)
}
}
14 changes: 7 additions & 7 deletions base/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@ import (
"context"
"testing"

"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/dsref"
"github.com/qri-io/qri/logbook"
"github.com/qri-io/qri/repo"
)

func TestDatasetLog(t *testing.T) {
func TestDatasetLogFromHistory(t *testing.T) {
ctx := context.Background()
r := newTestRepo(t)
addCitiesDataset(t, r)
head := updateCitiesDataset(t, r)
expectLen := 2

dlog, err := DatasetLog(ctx, r, head, 100, 0, true)
dlog, err := DatasetLogFromHistory(ctx, r, head, 0, 100, true)
if err != nil {
t.Error(err)
}
if len(dlog) != expectLen {
t.Errorf("log length mismatch. expected: %d, got: %d", expectLen, len(dlog))
t.Fatalf("log length mismatch. expected: %d, got: %d", expectLen, len(dlog))
}
if dlog[0].Dataset.Meta.Title != head.Dataset.Meta.Title {
t.Errorf("expected log with loadDataset == true to populate datasets")
}

dlog, err = DatasetLog(ctx, r, head, 100, 0, false)
dlog, err = DatasetLogFromHistory(ctx, r, head, 0, 100, false)
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -62,13 +62,13 @@ func TestConstructDatasetLogFromHistory(t *testing.T) {
}
r.SetLogbook(book)

ref := dsref.Ref{ Username: p.Peername, Name: "cities" }
ref := dsref.Ref{Username: p.Peername, Name: "cities"}

// confirm no history exists:
if _, err = book.Versions(ref, 0, 100); err == nil {
t.Errorf("expected versions for nonexistent history to fail")
}

// create some history
if err := ConstructDatasetLogFromHistory(ctx, r, ref); err != nil {
t.Errorf("building dataset history: %s", err)
Expand Down
3 changes: 2 additions & 1 deletion cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func TestRemoveOnlyTwoRevisions(t *testing.T) {
t.Skip(err.Error())
}

r := NewTestRepoRoot(t, "qri_test_remove_only_one_revision")
r := NewTestRepoRoot(t, "qri_test_remove_only_two_revisions")
defer r.Delete()

ctx, done := context.WithCancel(context.Background())
Expand Down Expand Up @@ -306,6 +306,7 @@ func TestRemoveOnlyTwoRevisions(t *testing.T) {

// Read body from the dataset that was saved.
dsPath := r.GetPathForDataset(0)
fmt.Println(dsPath)
actualBody := r.ReadBodyFromIPFS(dsPath + "/body.csv")

// Read the body from the testdata input file.
Expand Down
4 changes: 2 additions & 2 deletions cmd/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (o *LogOptions) Run() error {
},
}

refs := []repo.DatasetRef{}
refs := []lib.DatasetLogItem{}
if err := o.LogRequests.Log(p, &refs); err != nil {
if err == repo.ErrEmptyRef {
return lib.NewError(err, "please provide a dataset reference")
Expand All @@ -93,7 +93,7 @@ func (o *LogOptions) Run() error {

items := make([]fmt.Stringer, len(refs))
for i, r := range refs {
items[i] = logStringer(r)
items[i] = dslogItemStringer(r)
}

printItems(o.Out, items, page.Offset())
Expand Down
14 changes: 14 additions & 0 deletions cmd/stringers.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,17 @@ func (s logEntryStringer) String() string {
s.Note,
)
}

type dslogItemStringer lib.DatasetLogItem

func (s dslogItemStringer) String() string {
title := color.New(color.FgGreen, color.Bold).SprintFunc()
ts := color.New(color.Faint).SprintFunc()

return fmt.Sprintf("%s\t%s\t%s\t%s\n",
ts(s.Timestamp.Format(time.RFC3339)),
title(s.Ref.Name),
title(s.Ref.Path),
s.CommitTitle,
)
}
4 changes: 4 additions & 0 deletions fsi/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/qri-io/dataset"
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/logbook"
)

// InitParams encapsulates parameters for fsi.InitDataset
Expand Down Expand Up @@ -126,6 +127,9 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) {
}

err = fsi.repo.Logbook().WriteNameInit(context.TODO(), name)
if err == logbook.ErrNoLogbook {
err = nil
}
return name, err
}

Expand Down
12 changes: 10 additions & 2 deletions lib/datasets.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,16 @@ func (r *DatasetRequests) Remove(p *RemoveParams, res *RemoveResponse) error {
}

// Delete the specific number of revisions.
replace := log[p.Revision.Gen]
if err := actions.ModifyDataset(r.node, &ref, &replace, false /*isRename*/); err != nil {
dsr := log[p.Revision.Gen]
replace := &repo.DatasetRef{
Peername: dsr.Ref.Username,
Name: dsr.Ref.Name,
ProfileID: ref.ProfileID, // TODO (b5) - this is a cheat for now
Path: dsr.Ref.Path,
Published: dsr.Published,
}

if err := actions.ModifyDataset(r.node, &ref, replace, false /*isRename*/); err != nil {
return err
}
res.NumDeleted = p.Revision.Gen
Expand Down
4 changes: 2 additions & 2 deletions lib/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func completeDiffRefs(node *p2p.QriNode, left, right *string) (err error) {
ref := *right

lr := NewLogRequests(node, nil)
var res []repo.DatasetRef
var res []DatasetLogItem
err = lr.Log(&LogParams{
Ref: ref,
ListParams: ListParams{
Expand All @@ -120,7 +120,7 @@ func completeDiffRefs(node *p2p.QriNode, left, right *string) (err error) {
} else if len(res) == 1 {
return fmt.Errorf("dataset has only one version, nothing to diff against")
} else {
*left = res[1].String()
*left = res[1].Ref.String()
}
}

Expand Down
6 changes: 5 additions & 1 deletion lib/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/rpc"

"github.com/qri-io/qri/actions"
"github.com/qri-io/qri/base"
"github.com/qri-io/qri/logbook"
"github.com/qri-io/qri/p2p"
"github.com/qri-io/qri/repo"
Expand Down Expand Up @@ -41,8 +42,11 @@ type LogParams struct {
Ref string
}

// DatasetLogItem is a line item in a dataset response
type DatasetLogItem = base.DatasetLogItem

// Log returns the history of changes for a given dataset
func (r *LogRequests) Log(params *LogParams, res *[]repo.DatasetRef) (err error) {
func (r *LogRequests) Log(params *LogParams, res *[]DatasetLogItem) (err error) {
if r.cli != nil {
return r.cli.Call("LogRequests.Log", params, res)
}
Expand Down
Loading

0 comments on commit 1c38865

Please sign in to comment.