mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-22 01:17:11 +08:00
203 lines
4.2 KiB
Go
203 lines
4.2 KiB
Go
package commands
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
|
|
cmds "github.com/ipfs/go-ipfs/commands"
|
|
config "github.com/ipfs/go-ipfs/repo/config"
|
|
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
|
|
tour "github.com/ipfs/go-ipfs/tour"
|
|
)
|
|
|
|
var tourCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "An introduction to IPFS.",
|
|
ShortDescription: `
|
|
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
|
|
`,
|
|
},
|
|
|
|
Arguments: []cmds.Argument{
|
|
cmds.StringArg("id", false, false, "The id of the topic you would like to tour."),
|
|
},
|
|
Subcommands: map[string]*cmds.Command{
|
|
"list": cmdIpfsTourList,
|
|
"next": cmdIpfsTourNext,
|
|
"restart": cmdIpfsTourRestart,
|
|
},
|
|
Run: tourRunFunc,
|
|
}
|
|
|
|
func tourRunFunc(req cmds.Request, res cmds.Response) {
|
|
|
|
cfg, err := req.InvocContext().GetConfig()
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
|
|
id := tour.TopicID(cfg.Tour.Last)
|
|
if len(req.Arguments()) > 0 {
|
|
id = tour.TopicID(req.Arguments()[0])
|
|
}
|
|
|
|
w := new(bytes.Buffer)
|
|
t, err := tourGet(id)
|
|
if err != nil {
|
|
|
|
// If no topic exists for this id, we handle this error right here.
|
|
// To help the user achieve the task, we construct a response
|
|
// comprised of...
|
|
// 1) a simple error message
|
|
// 2) the full list of topics
|
|
|
|
fmt.Fprintln(w, "ERROR")
|
|
fmt.Fprintln(w, err)
|
|
fmt.Fprintln(w, "")
|
|
fprintTourList(w, tour.TopicID(cfg.Tour.Last))
|
|
res.SetOutput(w)
|
|
|
|
return
|
|
}
|
|
|
|
fprintTourShow(w, t)
|
|
res.SetOutput(w)
|
|
}
|
|
|
|
var cmdIpfsTourNext = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Show the next IPFS Tour topic.",
|
|
},
|
|
|
|
Run: func(req cmds.Request, res cmds.Response) {
|
|
w := new(bytes.Buffer)
|
|
path := req.InvocContext().ConfigRoot
|
|
cfg, err := req.InvocContext().GetConfig()
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
|
|
id := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
|
|
topic, err := tourGet(id)
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
if err := fprintTourShow(w, topic); err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
|
|
// topic changed, not last. write it out.
|
|
if string(id) != cfg.Tour.Last {
|
|
cfg.Tour.Last = string(id)
|
|
err := writeConfig(path, cfg)
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
}
|
|
|
|
res.SetOutput(w)
|
|
},
|
|
}
|
|
|
|
var cmdIpfsTourRestart = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Restart the IPFS Tour.",
|
|
},
|
|
|
|
Run: func(req cmds.Request, res cmds.Response) {
|
|
path := req.InvocContext().ConfigRoot
|
|
cfg, err := req.InvocContext().GetConfig()
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
|
|
cfg.Tour.Last = ""
|
|
err = writeConfig(path, cfg)
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
},
|
|
}
|
|
|
|
var cmdIpfsTourList = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Show a list of IPFS Tour topics.",
|
|
},
|
|
|
|
Run: func(req cmds.Request, res cmds.Response) {
|
|
cfg, err := req.InvocContext().GetConfig()
|
|
if err != nil {
|
|
res.SetError(err, cmds.ErrNormal)
|
|
return
|
|
}
|
|
|
|
w := new(bytes.Buffer)
|
|
fprintTourList(w, tour.TopicID(cfg.Tour.Last))
|
|
res.SetOutput(w)
|
|
},
|
|
}
|
|
|
|
func fprintTourList(w io.Writer, lastid tour.ID) {
|
|
for _, id := range tour.IDs {
|
|
c := ' '
|
|
switch {
|
|
case id == lastid:
|
|
c = '*'
|
|
case id.LessThan(lastid):
|
|
c = '✓'
|
|
}
|
|
|
|
t := tour.Topics[id]
|
|
fmt.Fprintf(w, "- %c %-5.5s %s\n", c, id, t.Title)
|
|
}
|
|
}
|
|
|
|
// fprintTourShow writes a text-formatted topic to the writer
|
|
func fprintTourShow(w io.Writer, t *tour.Topic) error {
|
|
tmpl := `
|
|
Tour {{ .ID }} - {{ .Title }}
|
|
|
|
{{ .Text }}
|
|
|
|
`
|
|
ttempl, err := template.New("tour").Parse(tmpl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ttempl.Execute(w, t)
|
|
}
|
|
|
|
// tourGet returns the topic given its ID. Returns an error if topic does not
|
|
// exist.
|
|
func tourGet(id tour.ID) (*tour.Topic, error) {
|
|
t, found := tour.Topics[id]
|
|
if !found {
|
|
return nil, fmt.Errorf("no topic with id: %s", id)
|
|
}
|
|
return &t, nil
|
|
}
|
|
|
|
// TODO share func
|
|
func writeConfig(path string, cfg *config.Config) error {
|
|
// NB: This needs to run on the daemon.
|
|
r, err := fsrepo.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer r.Close()
|
|
return r.SetConfig(cfg)
|
|
}
|