Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ipfs tour #213

Merged
merged 2 commits into from
Oct 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions cmd/ipfs/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,21 +187,6 @@ func bootstrapListCmd(c *commander.Command, inp []string) error {
return nil
}

func writeConfig(c *commander.Command, cfg *config.Config) error {

confdir, err := getConfigDir(c)
if err != nil {
return err
}

filename, err := config.Filename(confdir)
if err != nil {
return err
}

return config.WriteConfigFile(filename, cfg)
}

func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
split := func(addr string) (string, string) {
idx := strings.LastIndex(addr, "/")
Expand Down
22 changes: 19 additions & 3 deletions cmd/ipfs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package main
import (
"errors"
"fmt"
"io"
"os"
"os/exec"

"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
config "github.com/jbenet/go-ipfs/config"
u "github.com/jbenet/go-ipfs/util"
"io"
"os"
"os/exec"
)

var cmdIpfsConfig = &commander.Command{
Expand Down Expand Up @@ -125,3 +126,18 @@ func configEditor(filename string) error {
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
return cmd.Run()
}

func writeConfig(c *commander.Command, cfg *config.Config) error {

confdir, err := getConfigDir(c)
if err != nil {
return err
}

filename, err := config.Filename(confdir)
if err != nil {
return err
}

return config.WriteConfigFile(filename, cfg)
}
1 change: 1 addition & 0 deletions cmd/ipfs/ipfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Use "ipfs help <command>" for more information about a command.
cmdIpfsUpdate,
cmdIpfsLog,
cmdIpfsPin,
cmdIpfsTour,
},
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
}
Expand Down
134 changes: 134 additions & 0 deletions cmd/ipfs/tour.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// +build linux darwin freebsd

package main

import (
"fmt"

config "github.com/jbenet/go-ipfs/config"
tour "github.com/jbenet/go-ipfs/tour"

commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
)

var cmdIpfsTour = &commander.Command{
UsageLine: "tour [<number>]",
Short: "Take the IPFS Tour.",
Long: `ipfs tour - Take the IPFS Tour.

ipfs tour [<number>] - Show tour topic. Default to current.
ipfs tour next - Show the next tour topic.
ipfs tour list - Show a list of topics.
ipfs tour restart - Restart the tour.

This is a tour that takes you through various IPFS concepts,
features, and tools to make sure you get up to speed with
IPFS very quickly. To start, run:

ipfs tour
`,
Run: tourCmd,
Subcommands: []*commander.Command{
cmdIpfsTourNext,
cmdIpfsTourList,
cmdIpfsTourRestart,
},
}

var cmdIpfsTourNext = &commander.Command{
UsageLine: "next",
Short: "Show the next IPFS Tour topic.",
Run: tourNextCmd,
}

var cmdIpfsTourList = &commander.Command{
UsageLine: "list",
Short: "Show a list of IPFS Tour topics.",
Run: tourListCmd,
}

var cmdIpfsTourRestart = &commander.Command{
UsageLine: "restart",
Short: "Restart the IPFS Tour.",
Run: tourRestartCmd,
}

func tourCmd(c *commander.Command, inp []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}

topic := tour.TopicID(cfg.Tour.Last)
if len(inp) > 0 {
topic = tour.TopicID(inp[0])
}
return tourShow(topic)
}

func tourNextCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}

topic := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
if err := tourShow(topic); err != nil {
return err
}

// if topic didn't change (last) done
if string(topic) == cfg.Tour.Last {
return nil
}

// topic changed, not last. write it out.
cfg.Tour.Last = string(topic)
return writeConfig(c, cfg)
}

func tourListCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
lastid := tour.TopicID(cfg.Tour.Last)

for _, id := range tour.IDs {
c := ' '
switch {
case id == lastid:
c = '*'
case id.LessThan(lastid):
c = '✓'
}

t := tour.Topics[id]
fmt.Printf("- %c %-5.5s %s\n", c, id, t.Title)
}
return nil
}

func tourRestartCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}

cfg.Tour.Last = ""
return writeConfig(c, cfg)
}

func tourShow(id tour.ID) error {
t, found := tour.Topics[id]
if !found {
return fmt.Errorf("no topic with id: %s", id)
}

fmt.Printf("Tour %s - %s\n\n%s\n", t.ID, t.Title, t.Text)
return nil
}

func lastTour(cfg *config.Config) string {
return ""
}
7 changes: 7 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ func (bp *BootstrapPeer) String() string {
return bp.Address + "/" + bp.PeerID
}

// Tour stores the ipfs tour read-list and resume point
type Tour struct {
Last string // last tour topic read
// Done []string // all topics done so far
}

// Config is used to load IPFS config files.
type Config struct {
Identity Identity // local node's peer identity
Expand All @@ -55,6 +61,7 @@ type Config struct {
Mounts Mounts // local node's mount points
Version Version // local node's version management
Bootstrap []*BootstrapPeer // local nodes's bootstrap peers
Tour Tour // local node's tour position
}

// DefaultPathRoot is the path to the default config dir location.
Expand Down
26 changes: 26 additions & 0 deletions tour/all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tour

import "sort"

func init() {
for _, t := range allTopics {
Topics[t.ID] = t
IDs = append(IDs, t.ID)
}

sort.Sort(IDSlice(IDs))
}

// Topics contains a mapping of Tour Topic ID to Topic
var allTopics = []Topic{
Topic{
ID: ID("0"),
Title: "Hello Mars",
Text: "Hello Mars",
},
Topic{
ID: ID("0.1"),
Title: "Hello Mars 2",
Text: "Hello Mars 2",
},
}
86 changes: 86 additions & 0 deletions tour/tour.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package tour

import (
"strconv"
"strings"

u "github.com/jbenet/go-ipfs/util"
)

var log = u.Logger("tour")

// ID is a string identifier for topics
type ID string

// LessThan returns whether this ID is sorted earlier than another.
func (i ID) LessThan(o ID) bool {
return compareDottedInts(string(i), string(o))
}

// IDSlice implements the sort interface for ID slices.
type IDSlice []ID

func (a IDSlice) Len() int { return len(a) }
func (a IDSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a IDSlice) Less(i, j int) bool { return a[i].LessThan(a[j]) }

// Topic is a type of objects that structures a tour topic.
type Topic struct {
ID ID
Title string
Text string
}

// Topics is a sorted list of topic IDs
var IDs []ID

// Topics contains a mapping of Tour Topic ID to Topic
var Topics = map[ID]Topic{}

// NextTopic returns the next in-order topic
func NextTopic(topic ID) ID {
for _, id := range IDs {
if topic.LessThan(id) {
return id
}
}
return topic // last one, it seems.
}

// TopicID returns a valid tour topic ID from given string
func TopicID(t string) ID {
if t == "" { // if empty, use first ID
return IDs[0]
}
return ID(t)
}

func compareDottedInts(i, o string) bool {
is := strings.Split(i, ".")
os := strings.Split(o, ".")

for n, vis := range is {
if n >= len(os) {
return false // os is smaller.
}

vos := os[n]
ivis, err1 := strconv.Atoi(vis)
ivos, err2 := strconv.Atoi(vos)
if err1 != nil || err2 != nil {
log.Error(err1)
log.Error(err2)
panic("tour ID LessThan: not an int")
}

if ivis < ivos {
return true
}

if ivis > ivos {
return false
}
}

return len(os) > len(is)
}