Skip to content

Commit e633ecc

Browse files
authored
Merge pull request #5477 from kjzz/fix/publish
error when publishing ipns records without a running daemon
2 parents 87250b1 + 5676eb5 commit e633ecc

File tree

5 files changed

+72
-31
lines changed

5 files changed

+72
-31
lines changed

core/commands/name/ipns.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ type ResolvedPath struct {
2525
Path path.Path
2626
}
2727

28+
const (
29+
recursiveOptionName = "recursive"
30+
nocacheOptionName = "nocache"
31+
dhtRecordCountOptionName = "dht-record-count"
32+
dhtTimeoutOptionName = "dht-timeout"
33+
)
34+
2835
var IpnsCmd = &cmds.Command{
2936
Helptext: cmdkit.HelpText{
3037
Tagline: "Resolve IPNS names.",
@@ -67,10 +74,10 @@ Resolve the value of a dnslink:
6774
cmdkit.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID."),
6875
},
6976
Options: []cmdkit.Option{
70-
cmdkit.BoolOption("recursive", "r", "Resolve until the result is not an IPNS name."),
71-
cmdkit.BoolOption("nocache", "n", "Do not use cached entries."),
72-
cmdkit.UintOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."),
73-
cmdkit.StringOption("dht-timeout", "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
77+
cmdkit.BoolOption(recursiveOptionName, "r", "Resolve until the result is not an IPNS name."),
78+
cmdkit.BoolOption(nocacheOptionName, "n", "Do not use cached entries."),
79+
cmdkit.UintOption(dhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."),
80+
cmdkit.StringOption(dhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
7481
},
7582
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
7683
n, err := cmdenv.GetNode(env)
@@ -119,9 +126,10 @@ Resolve the value of a dnslink:
119126
name = req.Arguments[0]
120127
}
121128

122-
recursive, _ := req.Options["recursive"].(bool)
123-
rc, rcok := req.Options["dht-record-count"].(int)
124-
dhtt, dhttok := req.Options["dht-timeout"].(string)
129+
recursive, _ := req.Options[recursiveOptionName].(bool)
130+
rc, rcok := req.Options[dhtRecordCountOptionName].(int)
131+
dhtt, dhttok := req.Options[dhtTimeoutOptionName].(string)
132+
125133
var ropts []nsopts.ResolveOpt
126134
if !recursive {
127135
ropts = append(ropts, nsopts.Depth(1))

core/commands/name/publish.go

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ import (
1919
path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"
2020
)
2121

22+
var (
23+
errAllowOffline = errors.New("can't publish while offline: pass `--allow-offline` to override")
24+
errIpnsMount = errors.New("cannot manually publish while IPNS is mounted")
25+
errIdentityLoad = errors.New("identity not loaded")
26+
)
27+
28+
const (
29+
ipfsPathOptionName = "ipfs-path"
30+
resolveOptionName = "resolve"
31+
allowOfflineOptionName = "allow-offline"
32+
lifeTimeOptionName = "lifetime"
33+
ttlOptionName = "ttl"
34+
keyOptionName = "key"
35+
)
36+
2237
var PublishCmd = &cmds.Command{
2338
Helptext: cmdkit.HelpText{
2439
Tagline: "Publish IPNS names.",
@@ -60,16 +75,17 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
6075
},
6176

6277
Arguments: []cmdkit.Argument{
63-
cmdkit.StringArg("ipfs-path", true, false, "ipfs path of the object to be published.").EnableStdin(),
78+
cmdkit.StringArg(ipfsPathOptionName, true, false, "ipfs path of the object to be published.").EnableStdin(),
6479
},
6580
Options: []cmdkit.Option{
66-
cmdkit.BoolOption("resolve", "Resolve given path before publishing.").WithDefault(true),
67-
cmdkit.StringOption("lifetime", "t",
81+
cmdkit.BoolOption(resolveOptionName, "Resolve given path before publishing.").WithDefault(true),
82+
cmdkit.StringOption(lifeTimeOptionName, "t",
6883
`Time duration that the record will be valid for. <<default>>
6984
This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are
7085
"ns", "us" (or "µs"), "ms", "s", "m", "h".`).WithDefault("24h"),
71-
cmdkit.StringOption("ttl", "Time duration this record should be cached for (caution: experimental)."),
72-
cmdkit.StringOption("key", "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'. Default: <<default>>.").WithDefault("self"),
86+
cmdkit.BoolOption(allowOfflineOptionName, "When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing."),
87+
cmdkit.StringOption(ttlOptionName, "Time duration this record should be cached for (caution: experimental)."),
88+
cmdkit.StringOption(keyOptionName, "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'. Default: <<default>>.").WithDefault("self"),
7389
},
7490
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
7591
n, err := cmdenv.GetNode(env)
@@ -78,7 +94,12 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
7894
return
7995
}
8096

97+
allowOffline, _ := req.Options[allowOfflineOptionName].(bool)
8198
if !n.OnlineMode() {
99+
if !allowOffline {
100+
res.SetError(errAllowOffline, cmdkit.ErrNormal)
101+
return
102+
}
82103
err := n.SetupOfflineRouting()
83104
if err != nil {
84105
res.SetError(err, cmdkit.ErrNormal)
@@ -87,22 +108,22 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
87108
}
88109

89110
if n.Mounts.Ipns != nil && n.Mounts.Ipns.IsActive() {
90-
res.SetError(errors.New("cannot manually publish while IPNS is mounted"), cmdkit.ErrNormal)
111+
res.SetError(errIpnsMount, cmdkit.ErrNormal)
91112
return
92113
}
93114

94115
pstr := req.Arguments[0]
95116

96117
if n.Identity == "" {
97-
res.SetError(errors.New("identity not loaded"), cmdkit.ErrNormal)
118+
res.SetError(errIdentityLoad, cmdkit.ErrNormal)
98119
return
99120
}
100121

101122
popts := new(publishOpts)
102123

103-
popts.verifyExists, _ = req.Options["resolve"].(bool)
124+
popts.verifyExists, _ = req.Options[resolveOptionName].(bool)
104125

105-
validtime, _ := req.Options["lifetime"].(string)
126+
validtime, _ := req.Options[lifeTimeOptionName].(string)
106127
d, err := time.ParseDuration(validtime)
107128
if err != nil {
108129
res.SetError(fmt.Errorf("error parsing lifetime option: %s", err), cmdkit.ErrNormal)
@@ -112,7 +133,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
112133
popts.pubValidTime = d
113134

114135
ctx := req.Context
115-
if ttl, found := req.Options["ttl"].(string); found {
136+
if ttl, found := req.Options[ttlOptionName].(string); found {
116137
d, err := time.ParseDuration(ttl)
117138
if err != nil {
118139
res.SetError(err, cmdkit.ErrNormal)
@@ -122,7 +143,7 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
122143
ctx = context.WithValue(ctx, "ipns-publish-ttl", d)
123144
}
124145

125-
kname, _ := req.Options["key"].(string)
146+
kname, _ := req.Options[keyOptionName].(string)
126147
k, err := keylookup(n, kname)
127148
if err != nil {
128149
res.SetError(err, cmdkit.ErrNormal)

test/sharness/t0100-name.sh

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ test_init_ipfs
1212

1313
# test publishing a hash
1414

15-
test_expect_success "'ipfs name publish' succeeds" '
15+
16+
test_expect_success "'ipfs name publish --allow-offline' succeeds" '
1617
PEERID=`ipfs id --format="<id>"` &&
1718
test_check_peerid "${PEERID}" &&
18-
ipfs name publish "/ipfs/$HASH_WELCOME_DOCS" >publish_out
19+
ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS" >publish_out
1920
'
2021

2122
test_expect_success "publish output looks good" '
@@ -34,10 +35,10 @@ test_expect_success "resolve output looks good" '
3435

3536
# now test with a path
3637

37-
test_expect_success "'ipfs name publish' succeeds" '
38+
test_expect_success "'ipfs name publish --allow-offline' succeeds" '
3839
PEERID=`ipfs id --format="<id>"` &&
3940
test_check_peerid "${PEERID}" &&
40-
ipfs name publish "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out
41+
ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out
4142
'
4243

4344
test_expect_success "publish a path looks good" '
@@ -62,11 +63,11 @@ test_expect_success "ipfs cat on published content succeeds" '
6263

6364
# publish with an explicit node ID
6465

65-
test_expect_failure "'ipfs name publish <local-id> <hash>' succeeds" '
66+
test_expect_failure "'ipfs name publish --allow-offline <local-id> <hash>' succeeds" '
6667
PEERID=`ipfs id --format="<id>"` &&
6768
test_check_peerid "${PEERID}" &&
68-
echo ipfs name publish "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" &&
69-
ipfs name publish "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
69+
echo ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" &&
70+
ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
7071
'
7172

7273
test_expect_failure "publish with our explicit node ID looks good" '
@@ -81,8 +82,8 @@ test_expect_success "generate and verify a new key" '
8182
test_check_peerid "${NEWID}"
8283
'
8384

84-
test_expect_success "'ipfs name publish --key=<peer-id> <hash>' succeeds" '
85-
ipfs name publish --key=${NEWID} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
85+
test_expect_success "'ipfs name publis --allow-offline --key=<peer-id> <hash>' succeeds" '
86+
ipfs name publish --allow-offline --key=${NEWID} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish
8687
'
8788

8889
test_expect_success "publish an explicit node ID as key name looks good" '
@@ -94,7 +95,7 @@ test_expect_success "publish an explicit node ID as key name looks good" '
9495
# test publishing nothing
9596

9697
test_expect_success "'ipfs name publish' fails" '
97-
printf '' | test_expect_code 1 ipfs name publish >publish_out 2>&1
98+
printf '' | test_expect_code 1 ipfs name publish --allow-offline >publish_out 2>&1
9899
'
99100

100101
test_expect_success "publish output has the correct error" '
@@ -115,4 +116,15 @@ test_expect_success "empty request to name publish doesn't panic and returns err
115116
test_kill_ipfs_daemon
116117

117118

119+
# Test daemon in offline mode
120+
test_launch_ipfs_daemon --offline
121+
122+
test_expect_success "'ipfs name publish' fails offline mode" '
123+
PEERID=`ipfs id --format="<id>"` &&
124+
test_check_peerid "${PEERID}" &&
125+
test_expect_code 1 ipfs name publish "/ipfs/$HASH_WELCOME_DOCS"
126+
'
127+
128+
test_kill_ipfs_daemon
129+
118130
test_done

test/sharness/t0110-gateway.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ test_expect_success "GET IPFS non existent file returns code expected (404)" '
6262
'
6363

6464
test_expect_failure "GET IPNS path succeeds" '
65-
ipfs name publish "$HASH" &&
65+
ipfs name publish --allow-offline "$HASH" &&
6666
PEERID=$(ipfs config Identity.PeerID) &&
6767
test_check_peerid "$PEERID" &&
6868
curl -sfo actual "http://127.0.0.1:$port/ipns/$PEERID"

test/sharness/t0160-resolve.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test_resolve_setup_name() {
1919

2020
test_expect_success "resolve: prepare name" '
2121
id_hash=$(ipfs id -f="<id>") &&
22-
ipfs name publish "$ref" &&
22+
ipfs name publish --allow-offline "$ref" &&
2323
printf "$ref\n" >expected_nameval &&
2424
ipfs name resolve >actual_nameval &&
2525
test_cmp expected_nameval actual_nameval
@@ -31,7 +31,7 @@ test_resolve_setup_name_fail() {
3131

3232
test_expect_failure "resolve: prepare name" '
3333
id_hash=$(ipfs id -f="<id>") &&
34-
ipfs name publish "$ref" &&
34+
ipfs name publish --allow-offline "$ref" &&
3535
printf "$ref" >expected_nameval &&
3636
ipfs name resolve >actual_nameval &&
3737
test_cmp expected_nameval actual_nameval

0 commit comments

Comments
 (0)