-
Notifications
You must be signed in to change notification settings - Fork 0
/
publish.go
160 lines (130 loc) · 4.36 KB
/
publish.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package commands
import (
"errors"
"fmt"
"io"
"strings"
"time"
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
key "github.com/ipfs/go-ipfs/blocks/key"
cmds "github.com/ipfs/go-ipfs/commands"
core "github.com/ipfs/go-ipfs/core"
path "github.com/ipfs/go-ipfs/path"
crypto "gx/ipfs/QmUEUu1CM8bxBJxc3ZLojAi8evhTr4byQogWstABet79oY/go-libp2p-crypto"
)
var errNotOnline = errors.New("This command must be run in online mode. Try running 'ipfs daemon' first.")
var PublishCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Publish an object to IPNS.",
ShortDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In publish, the
default value of <name> is your own identity public key.
`,
LongDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In publish, the
default value of <name> is your own identity public key.
Examples:
Publish an <ipfs-path> to your identity name:
> ipfs name publish /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Published to QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n: /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Publish an <ipfs-path> to another public key (not implemented):
> ipfs name publish /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
Published to QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n: /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
`,
},
Arguments: []cmds.Argument{
cmds.StringArg("ipfs-path", true, false, "IPFS path of the object to be published.").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption("resolve", "Resolve given path before publishing.").Default(true),
cmds.StringOption("lifetime", "t", `Time duration that the record will be valid for.
This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are
"ns", "us" (or "µs"), "ms", "s", "m", "h".
`).Default("24h"),
cmds.StringOption("ttl", "Time duration this record should be cached for (caution: experimental)."),
},
Run: func(req cmds.Request, res cmds.Response) {
log.Debug("Begin Publish")
n, err := req.InvocContext().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
if !n.OnlineMode() {
err := n.SetupOfflineRouting()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
}
if n.Mounts.Ipns != nil && n.Mounts.Ipns.IsActive() {
res.SetError(errors.New("You cannot manually publish while IPNS is mounted."), cmds.ErrNormal)
return
}
pstr := req.Arguments()[0]
if n.Identity == "" {
res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal)
return
}
popts := new(publishOpts)
popts.verifyExists, _, _ = req.Option("resolve").Bool()
validtime, _, _ := req.Option("lifetime").String()
d, err := time.ParseDuration(validtime)
if err != nil {
res.SetError(fmt.Errorf("error parsing lifetime option: %s", err), cmds.ErrNormal)
return
}
popts.pubValidTime = d
ctx := req.Context()
if ttl, found, _ := req.Option("ttl").String(); found {
d, err := time.ParseDuration(ttl)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
ctx = context.WithValue(ctx, "ipns-publish-ttl", d)
}
output, err := publish(ctx, n, n.PrivateKey, path.Path(pstr), popts)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
res.SetOutput(output)
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
v := res.Output().(*IpnsEntry)
s := fmt.Sprintf("Published to %s: %s\n", v.Name, v.Value)
return strings.NewReader(s), nil
},
},
Type: IpnsEntry{},
}
type publishOpts struct {
verifyExists bool
pubValidTime time.Duration
}
func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.Path, opts *publishOpts) (*IpnsEntry, error) {
if opts.verifyExists {
// verify the path exists
_, err := core.Resolve(ctx, n, ref)
if err != nil {
return nil, err
}
}
eol := time.Now().Add(opts.pubValidTime)
err := n.Namesys.PublishWithEOL(ctx, k, ref, eol)
if err != nil {
return nil, err
}
hash, err := k.GetPublic().Hash()
if err != nil {
return nil, err
}
return &IpnsEntry{
Name: key.Key(hash).String(),
Value: ref.String(),
}, nil
}