Skip to content

Commit 85d6892

Browse files
committed
feat(registry cmd): add commands for working with registries
I've refactored a bunch of the logic around working with registries to make the process more explicit & controllable.
1 parent 5d8cac9 commit 85d6892

File tree

11 files changed

+281
-14
lines changed

11 files changed

+281
-14
lines changed

cmd/add.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var (
2424
addDsPassive bool
2525
addDsShowValidation bool
2626
addDsPrivate bool
27+
addDsNoRegistry bool
2728
addDsSecrets []string
2829
)
2930

@@ -149,6 +150,7 @@ continue?`, true) {
149150
p := &core.SaveParams{
150151
Dataset: dsp,
151152
Private: addDsPrivate,
153+
Publish: !addDsNoRegistry,
152154
}
153155

154156
req, err := datasetRequests(false)
@@ -187,6 +189,7 @@ func init() {
187189
datasetAddCmd.Flags().StringVarP(&addDsMessage, "message", "m", "", "commit message")
188190
datasetAddCmd.Flags().BoolVarP(&addDsPrivate, "private", "", false, "make dataset private. WARNING: not yet implimented. Please refer to https://github.com/qri-io/qri/issues/291 for updates")
189191
datasetAddCmd.Flags().StringSliceVar(&addDsSecrets, "secrets", nil, "transform secrets as comma separated key,value,key,value,... sequence")
192+
datasetAddCmd.Flags().BoolVarP(&addDsNoRegistry, "no-registry", "n", false, "don't publish this dataset to the registry")
190193
// datasetAddCmd.Flags().BoolVarP(&addDsShowValidation, "show-validation", "s", false, "display a list of validation errors upon adding")
191194
RootCmd.AddCommand(datasetAddCmd)
192195
}

cmd/cmd_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ func TestCommandsIntegration(t *testing.T) {
162162
{"diff", "me/movies", "me/movies2", "-d", "detail"},
163163
{"export", "--dataset", "-o" + path, "me/movies"},
164164
{"export", "--all", "-o" + path, "--format=json", "--data-format=json", "me/movies"},
165+
{"registry", "unpublish", "me/movies"},
166+
{"registry", "publish", "me/movies"},
165167
{"rename", "me/movies", "me/movie"},
166168
{"data", "--limit=1", "--data-format=cbor", "me/movie"},
167169
{"validate", "me/movie"},

cmd/registry.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package cmd
2+
3+
import (
4+
"github.com/qri-io/qri/repo"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
// RegistryCmd is the subcommand for working with configured registries
9+
var RegistryCmd = &cobra.Command{
10+
Use: "registry",
11+
Short: "commands for working with a qri registry",
12+
Long: `Registries are federated public records of datasets and peers.
13+
These records form a public facing central lookup for your datasets, so others
14+
can find them through search tools and via web links. You can use registry
15+
commands to control how your datasets are published to registries, opting out
16+
on a dataset-by-dataset basis.
17+
18+
By default qri is configured to publish to https://registry.qri.io,
19+
the main public collection of datasets & peers. "qri add" and "qri update"
20+
default to publishing to a registry as part of dataset creation unless run
21+
with the "no-registry" flag.
22+
23+
Unpublished dataset info will be held locally so you can still interact
24+
with it. And your datasets will be available to others peers when you run
25+
"qri connect", but will not show up in search results, and will not be
26+
displayed on lists of registry datasets.
27+
28+
Qri is designed to work without a registry should you want to opt out of
29+
centralized listing entirely, but know that peers who *do* participate in
30+
registries may choose to deprioritize connections with you. Opting out of a
31+
registry entirely is better left to advanced users.
32+
33+
You can opt out of registries entirely by running:
34+
$ qri config set registry.location ""`,
35+
36+
Annotations: map[string]string{
37+
"group": "network",
38+
},
39+
}
40+
41+
// publishCmd represents the export command
42+
var publishCmd = &cobra.Command{
43+
Use: "publish",
44+
Short: "publish dataset info to the registry",
45+
Example: ` Publish a dataset you've created to the registry:
46+
$ qri registry publish me/dataset_name`,
47+
PreRun: func(cmd *cobra.Command, args []string) {
48+
loadConfig()
49+
},
50+
Args: cobra.MinimumNArgs(1),
51+
Run: func(cmd *cobra.Command, args []string) {
52+
req, err := registryRequests(false)
53+
ExitIfErr(err)
54+
55+
var res bool
56+
for _, arg := range args {
57+
ref, err := repo.ParseDatasetRef(arg)
58+
ExitIfErr(err)
59+
60+
err = req.Publish(&ref, &res)
61+
ExitIfErr(err)
62+
printInfo("published dataset %s", ref)
63+
}
64+
},
65+
}
66+
67+
// unpublishCmd represents the export command
68+
var unpublishCmd = &cobra.Command{
69+
Use: "unpublish",
70+
Short: "remove dataset info from the registry",
71+
Example: ` Remove a dataset from the registry:
72+
$ qri registry unpublish me/dataset_name`,
73+
PreRun: func(cmd *cobra.Command, args []string) {
74+
loadConfig()
75+
},
76+
Args: cobra.MinimumNArgs(1),
77+
Run: func(cmd *cobra.Command, args []string) {
78+
req, err := registryRequests(false)
79+
ExitIfErr(err)
80+
81+
var res bool
82+
for _, arg := range args {
83+
ref, err := repo.ParseDatasetRef(arg)
84+
ExitIfErr(err)
85+
86+
err = req.Unpublish(&ref, &res)
87+
ExitIfErr(err)
88+
printInfo("unpublished dataset %s", ref)
89+
}
90+
},
91+
}
92+
93+
func init() {
94+
RegistryCmd.AddCommand(publishCmd)
95+
RegistryCmd.AddCommand(unpublishCmd)
96+
RootCmd.AddCommand(RegistryCmd)
97+
}

cmd/repo.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,28 @@ func datasetRequests(online bool) (*core.DatasetRequests, error) {
120120
return req, nil
121121
}
122122

123+
func registryRequests(online bool) (*core.RegistryRequests, error) {
124+
if cli := rpcConn(); cli != nil {
125+
return core.NewRegistryRequests(nil, cli), nil
126+
}
127+
128+
if !online {
129+
// TODO - make this not terrible
130+
r, cli, err := repoOrClient(online)
131+
if err != nil {
132+
return nil, err
133+
}
134+
return core.NewRegistryRequests(r, cli), nil
135+
}
136+
137+
n, err := qriNode(online)
138+
if err != nil {
139+
return nil, err
140+
}
141+
142+
return core.NewRegistryRequests(n.Repo, nil), nil
143+
}
144+
123145
func renderRequests(online bool) (*core.RenderRequests, error) {
124146
if cli := rpcConn(); cli != nil {
125147
return core.NewRenderRequests(nil, cli), nil

cmd/save.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var (
2323
savePassive bool
2424
saveRescursive bool
2525
saveShowValidation bool
26+
saveNoRegistry bool
2627
saveSecrets []string
2728
)
2829

@@ -113,6 +114,7 @@ continue?`, true) {
113114
p := &core.SaveParams{
114115
Dataset: dsp,
115116
Private: false,
117+
Publish: !saveNoRegistry,
116118
}
117119

118120
req, err := datasetRequests(false)
@@ -150,5 +152,6 @@ func init() {
150152
saveCmd.Flags().StringVarP(&saveDataPath, "data", "", "", "path to file or url to initialize from")
151153
saveCmd.Flags().BoolVarP(&saveShowValidation, "show-validation", "s", false, "display a list of validation errors upon adding")
152154
saveCmd.Flags().StringSliceVar(&saveSecrets, "secrets", nil, "transform secrets as comma separated key,value,key,value,... sequence")
155+
saveCmd.Flags().BoolVarP(&saveNoRegistry, "no-registry", "n", false, "don't publish this dataset to the registry")
153156
RootCmd.AddCommand(saveCmd)
154157
}

core/core.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func Receivers(node *p2p.QriNode) []Requests {
2727

2828
return []Requests{
2929
NewDatasetRequestsWithNode(r, nil, node),
30+
NewRegistryRequests(r, nil),
3031
NewHistoryRequests(r, nil),
3132
NewPeerRequests(node, nil),
3233
NewProfileRequests(r, nil),

core/core_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ func TestReceivers(t *testing.T) {
1818
}
1919

2020
reqs := Receivers(node)
21-
if len(reqs) != 6 {
22-
t.Errorf("unexpected number of receivers returned. expected: %d. got: %d", 6, len(reqs))
21+
if len(reqs) != 7 {
22+
t.Errorf("unexpected number of receivers returned. expected: %d. got: %d\nhave you added/removed a receiver?", 7, len(reqs))
2323
return
2424
}
2525
}

core/datasets.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ func (r *DatasetRequests) Get(p *repo.DatasetRef, res *repo.DatasetRef) (err err
263263
type SaveParams struct {
264264
Dataset *dataset.DatasetPod // dataset to create
265265
Private bool // option to make dataset private. private data is not currently implimented, see https://github.com/qri-io/qri/issues/291 for updates
266+
Publish bool
266267
}
267268

268269
// Init creates a new qri dataset from a source of data
@@ -363,6 +364,15 @@ func (r *DatasetRequests) Init(p *SaveParams, res *repo.DatasetRef) (err error)
363364
return err
364365
}
365366

367+
if p.Publish {
368+
fmt.Println("posting dataset to registry ...")
369+
var done bool
370+
if err = NewRegistryRequests(r.repo, nil).Publish(res, &done); err != nil {
371+
return err
372+
}
373+
fmt.Println("done")
374+
}
375+
366376
return r.repo.ReadDataset(res)
367377
}
368378

@@ -476,6 +486,15 @@ func (r *DatasetRequests) Save(p *SaveParams, res *repo.DatasetRef) (err error)
476486
}
477487
ref.Dataset = ds.Encode()
478488

489+
if p.Publish {
490+
fmt.Println("posting dataset to registry ...")
491+
var done bool
492+
if err = NewRegistryRequests(r.repo, nil).Publish(&ref, &done); err != nil {
493+
return err
494+
}
495+
fmt.Println("done")
496+
}
497+
479498
*res = ref
480499
return nil
481500
}

core/registry.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package core
2+
3+
import (
4+
"fmt"
5+
"net/rpc"
6+
7+
"github.com/qri-io/qri/repo"
8+
"github.com/qri-io/qri/repo/actions"
9+
)
10+
11+
// RegistryRequests defines business logic for working with registries
12+
type RegistryRequests struct {
13+
repo actions.Registry
14+
cli *rpc.Client
15+
}
16+
17+
// CoreRequestsName implements the Requests interface
18+
func (RegistryRequests) CoreRequestsName() string { return "registry" }
19+
20+
// NewRegistryRequests creates a DatasetRequests pointer from either a repo
21+
// or an rpc.Client
22+
func NewRegistryRequests(r repo.Repo, cli *rpc.Client) *RegistryRequests {
23+
if r != nil && cli != nil {
24+
panic(fmt.Errorf("both repo and client supplied to NewRegistryRequests"))
25+
}
26+
27+
return &RegistryRequests{
28+
repo: actions.Registry{r},
29+
cli: cli,
30+
}
31+
}
32+
33+
// Publish a dataset to a registry
34+
func (r *RegistryRequests) Publish(ref *repo.DatasetRef, done *bool) error {
35+
if r.cli != nil {
36+
return r.cli.Call("RegistryRequests.Publish", ref, done)
37+
}
38+
return r.repo.Publish(*ref)
39+
}
40+
41+
// Unpublish a dataset from a registry
42+
func (r *RegistryRequests) Unpublish(ref *repo.DatasetRef, done *bool) error {
43+
if r.cli != nil {
44+
return r.cli.Call("RegistryRequests.Unpublish", ref, done)
45+
}
46+
return r.repo.Unpublish(*ref)
47+
}

repo/actions/dataset.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,6 @@ func (act Dataset) CreateDataset(name string, ds *dataset.Dataset, data cafs.Fil
6969
return
7070
}
7171

72-
if rc := act.Registry(); rc != nil {
73-
log.Debugf("posting dataset to registry: %s/%s", pro.Peername, name)
74-
dse := ds.Encode()
75-
// TODO - this should be set be dsfs.CreateDataset:
76-
dse.Path = path.String()
77-
78-
if e := rc.PutDataset(pro.Peername, name, dse, pro.PrivKey.GetPublic()); e != nil {
79-
// ignore registry errors
80-
log.Errorf("registering dataset: %s", e.Error())
81-
}
82-
}
83-
8472
if err = act.LogEvent(repo.ETDsCreated, ref); err != nil {
8573
return
8674
}

0 commit comments

Comments
 (0)