@cryptotaxi247 / kubo / commits / 6f7bab389

tour: command

Juan Batiz-Benet committed Oct 26, 2014 at 08:32 UTC 6f7bab389e4a52ed8bf03861c15ab42541791568
7 files changed +273 -18
cmd/ipfs/bootstrap.go
-15
@@ -187,21 +187,6 @@ func bootstrapListCmd(c *commander.Command, inp []string) error {
187 return nil
188 }
189
190 -func writeConfig(c *commander.Command, cfg *config.Config) error {
191 -
192 - confdir, err := getConfigDir(c)
193 - if err != nil {
194 - return err
195 - }
196 -
197 - filename, err := config.Filename(confdir)
198 - if err != nil {
199 - return err
200 - }
201 -
202 - return config.WriteConfigFile(filename, cfg)
203 -}
204 -
190 func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
191 split := func(addr string) (string, string) {
192 idx := strings.LastIndex(addr, "/")
cmd/ipfs/config.go
+19 -3
@@ -3,13 +3,14 @@ package main
3 import (
4 "errors"
5 "fmt"
6 + "io"
7 + "os"
8 + "os/exec"
9 +
10 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
11 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
12 config "github.com/jbenet/go-ipfs/config"
13 u "github.com/jbenet/go-ipfs/util"
10 - "io"
11 - "os"
12 - "os/exec"
14 )
15
16 var cmdIpfsConfig = &commander.Command{
@@ -125,3 +126,18 @@ func configEditor(filename string) error {
126 cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
127 return cmd.Run()
128 }
129 +
130 +func writeConfig(c *commander.Command, cfg *config.Config) error {
131 +
132 + confdir, err := getConfigDir(c)
133 + if err != nil {
134 + return err
135 + }
136 +
137 + filename, err := config.Filename(confdir)
138 + if err != nil {
139 + return err
140 + }
141 +
142 + return config.WriteConfigFile(filename, cfg)
143 +}
cmd/ipfs/ipfs.go
+1
@@ -73,6 +73,7 @@ Use "ipfs help <command>" for more information about a command.
73 cmdIpfsUpdate,
74 cmdIpfsLog,
75 cmdIpfsPin,
76 + cmdIpfsTour,
77 },
78 Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
79 }
cmd/ipfs/tour.go new
+134
@@ -0,0 +1,134 @@
1 +// +build linux darwin freebsd
2 +
3 +package main
4 +
5 +import (
6 + "fmt"
7 +
8 + config "github.com/jbenet/go-ipfs/config"
9 + tour "github.com/jbenet/go-ipfs/tour"
10 +
11 + commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
12 +)
13 +
14 +var cmdIpfsTour = &commander.Command{
15 + UsageLine: "tour [<number>]",
16 + Short: "Take the IPFS Tour.",
17 + Long: `ipfs tour - Take the IPFS Tour.
18 +
19 + ipfs tour [<number>] - Show tour topic. Default to current.
20 + ipfs tour next - Show the next tour topic.
21 + ipfs tour list - Show a list of topics.
22 + ipfs tour restart - Restart the tour.
23 +
24 +This is a tour that takes you through various IPFS concepts,
25 +features, and tools to make sure you get up to speed with
26 +IPFS very quickly. To start, run:
27 +
28 + ipfs tour
29 +`,
30 + Run: tourCmd,
31 + Subcommands: []*commander.Command{
32 + cmdIpfsTourNext,
33 + cmdIpfsTourList,
34 + cmdIpfsTourRestart,
35 + },
36 +}
37 +
38 +var cmdIpfsTourNext = &commander.Command{
39 + UsageLine: "next",
40 + Short: "Show the next IPFS Tour topic.",
41 + Run: tourNextCmd,
42 +}
43 +
44 +var cmdIpfsTourList = &commander.Command{
45 + UsageLine: "list",
46 + Short: "Show a list of IPFS Tour topics.",
47 + Run: tourListCmd,
48 +}
49 +
50 +var cmdIpfsTourRestart = &commander.Command{
51 + UsageLine: "restart",
52 + Short: "Restart the IPFS Tour.",
53 + Run: tourRestartCmd,
54 +}
55 +
56 +func tourCmd(c *commander.Command, inp []string) error {
57 + cfg, err := getConfig(c)
58 + if err != nil {
59 + return err
60 + }
61 +
62 + topic := tour.TopicID(cfg.Tour.Last)
63 + if len(inp) > 0 {
64 + topic = tour.TopicID(inp[0])
65 + }
66 + return tourShow(topic)
67 +}
68 +
69 +func tourNextCmd(c *commander.Command, _ []string) error {
70 + cfg, err := getConfig(c)
71 + if err != nil {
72 + return err
73 + }
74 +
75 + topic := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
76 + if err := tourShow(topic); err != nil {
77 + return err
78 + }
79 +
80 + // if topic didn't change (last) done
81 + if string(topic) == cfg.Tour.Last {
82 + return nil
83 + }
84 +
85 + // topic changed, not last. write it out.
86 + cfg.Tour.Last = string(topic)
87 + return writeConfig(c, cfg)
88 +}
89 +
90 +func tourListCmd(c *commander.Command, _ []string) error {
91 + cfg, err := getConfig(c)
92 + if err != nil {
93 + return err
94 + }
95 + lastid := tour.TopicID(cfg.Tour.Last)
96 +
97 + for _, id := range tour.IDs {
98 + c := ' '
99 + switch {
100 + case id == lastid:
101 + c = '*'
102 + case id.LessThan(lastid):
103 + c = '✓'
104 + }
105 +
106 + t := tour.Topics[id]
107 + fmt.Printf("- %c %5.5s %s\n", c, id, t.Title)
108 + }
109 + return nil
110 +}
111 +
112 +func tourRestartCmd(c *commander.Command, _ []string) error {
113 + cfg, err := getConfig(c)
114 + if err != nil {
115 + return err
116 + }
117 +
118 + cfg.Tour.Last = ""
119 + return writeConfig(c, cfg)
120 +}
121 +
122 +func tourShow(id tour.ID) error {
123 + t, found := tour.Topics[id]
124 + if !found {
125 + return fmt.Errorf("no topic with id: %s", id)
126 + }
127 +
128 + fmt.Printf("Tour %s - %s\n\n%s\n", t.ID, t.Title, t.Text)
129 + return nil
130 +}
131 +
132 +func lastTour(cfg *config.Config) string {
133 + return ""
134 +}
config/config.go
+7
@@ -47,6 +47,12 @@ func (bp *BootstrapPeer) String() string {
47 return bp.Address + "/" + bp.PeerID
48 }
49
50 +// Tour stores the ipfs tour read-list and resume point
51 +type Tour struct {
52 + Last string // last tour topic read
53 + // Done []string // all topics done so far
54 +}
55 +
56 // Config is used to load IPFS config files.
57 type Config struct {
58 Identity Identity // local node's peer identity
@@ -55,6 +61,7 @@ type Config struct {
61 Mounts Mounts // local node's mount points
62 Version Version // local node's version management
63 Bootstrap []*BootstrapPeer // local nodes's bootstrap peers
64 + Tour Tour // local node's tour position
65 }
66
67 // DefaultPathRoot is the path to the default config dir location.
tour/all.go new
+26
@@ -0,0 +1,26 @@
1 +package tour
2 +
3 +import "sort"
4 +
5 +func init() {
6 + for _, t := range allTopics {
7 + Topics[t.ID] = t
8 + IDs = append(IDs, t.ID)
9 + }
10 +
11 + sort.Sort(IDSlice(IDs))
12 +}
13 +
14 +// Topics contains a mapping of Tour Topic ID to Topic
15 +var allTopics = []Topic{
16 + Topic{
17 + ID: ID("0"),
18 + Title: "Hello Mars",
19 + Text: "Hello Mars",
20 + },
21 + Topic{
22 + ID: ID("0.1"),
23 + Title: "Hello Mars 2",
24 + Text: "Hello Mars 2",
25 + },
26 +}
tour/tour.go new
+86
@@ -0,0 +1,86 @@
1 +package tour
2 +
3 +import (
4 + "strconv"
5 + "strings"
6 +
7 + u "github.com/jbenet/go-ipfs/util"
8 +)
9 +
10 +var log = u.Logger("tour")
11 +
12 +// ID is a string identifier for topics
13 +type ID string
14 +
15 +// LessThan returns whether this ID is sorted earlier than another.
16 +func (i ID) LessThan(o ID) bool {
17 + return compareDottedInts(string(i), string(o))
18 +}
19 +
20 +// IDSlice implements the sort interface for ID slices.
21 +type IDSlice []ID
22 +
23 +func (a IDSlice) Len() int { return len(a) }
24 +func (a IDSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
25 +func (a IDSlice) Less(i, j int) bool { return a[i].LessThan(a[j]) }
26 +
27 +// Topic is a type of objects that structures a tour topic.
28 +type Topic struct {
29 + ID ID
30 + Title string
31 + Text string
32 +}
33 +
34 +// Topics is a sorted list of topic IDs
35 +var IDs []ID
36 +
37 +// Topics contains a mapping of Tour Topic ID to Topic
38 +var Topics = map[ID]Topic{}
39 +
40 +// NextTopic returns the next in-order topic
41 +func NextTopic(topic ID) ID {
42 + for _, id := range IDs {
43 + if topic.LessThan(id) {
44 + return id
45 + }
46 + }
47 + return topic // last one, it seems.
48 +}
49 +
50 +// TopicID returns a valid tour topic ID from given string
51 +func TopicID(t string) ID {
52 + if t == "" { // if empty, use first ID
53 + return IDs[0]
54 + }
55 + return ID(t)
56 +}
57 +
58 +func compareDottedInts(i, o string) bool {
59 + is := strings.Split(i, ".")
60 + os := strings.Split(o, ".")
61 +
62 + for n, vis := range is {
63 + if n >= len(os) {
64 + return false // os is smaller.
65 + }
66 +
67 + vos := os[n]
68 + ivis, err1 := strconv.Atoi(vis)
69 + ivos, err2 := strconv.Atoi(vos)
70 + if err1 != nil || err2 != nil {
71 + log.Error(err1)
72 + log.Error(err2)
73 + panic("tour ID LessThan: not an int")
74 + }
75 +
76 + if ivis < ivos {
77 + return true
78 + }
79 +
80 + if ivis > ivos {
81 + return false
82 + }
83 + }
84 +
85 + return len(os) > len(is)
86 +}