mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-26 04:47:45 +08:00
commit
0197fe6046
@ -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, "/")
|
||||
|
||||
@ -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{
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -73,6 +73,7 @@ Use "ipfs help <command>" for more information about a command.
|
||||
cmdIpfsUpdate,
|
||||
cmdIpfsLog,
|
||||
cmdIpfsPin,
|
||||
cmdIpfsTour,
|
||||
},
|
||||
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
|
||||
}
|
||||
|
||||
134
cmd/ipfs/tour.go
Normal file
134
cmd/ipfs/tour.go
Normal file
@ -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 ""
|
||||
}
|
||||
@ -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
|
||||
@ -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.
|
||||
|
||||
26
tour/all.go
Normal file
26
tour/all.go
Normal file
@ -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
tour/tour.go
Normal file
86
tour/tour.go
Normal file
@ -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)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user