Skip to content

Commit f36da26

Browse files
committed
feat: new export command.
export now follows our new command conventions
1 parent cae7dbd commit f36da26

File tree

2 files changed

+112
-23
lines changed

2 files changed

+112
-23
lines changed

cmd/cmd_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func TestCommandsIntegration(t *testing.T) {
9595
{"list"},
9696
{"save", "-f" + movies2FilePath, "-n" + "movies", "-m" + "commit_1"},
9797
{"log", "-n" + "movies"},
98-
// {"run", "select * from movies limit 5"},
98+
{"export", "--dataset", "movies", "-o" + path},
9999
{"rename", "movies", "movie"},
100100
{"validate", "-n" + "movie"},
101101
{"remove", "movie"},

cmd/export.go

Lines changed: 111 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
package cmd
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io"
7+
"io/ioutil"
68
"os"
9+
"path/filepath"
710

8-
"github.com/ipfs/go-datastore"
11+
"github.com/qri-io/dataset"
912
"github.com/qri-io/dataset/dsfs"
1013
"github.com/qri-io/dataset/dsutil"
1114
"github.com/qri-io/qri/core"
1215
"github.com/qri-io/qri/repo"
1316
"github.com/spf13/cobra"
1417
)
1518

19+
var (
20+
exportCmdDataset bool
21+
exportCmdMeta bool
22+
exportCmdStructure bool
23+
exportCmdData bool
24+
exportCmdTransform bool
25+
exportCmdVis bool
26+
)
27+
1628
// exportCmd represents the export command
1729
var exportCmd = &cobra.Command{
1830
Use: "export",
@@ -31,60 +43,137 @@ To export everything about a dataset, use the --dataset flag.`,
3143
return
3244
}
3345
path := cmd.Flag("output").Value.String()
34-
if path == "" {
35-
// TODO - support printing to stdout
36-
ErrExit(fmt.Errorf("please specify an output path"))
37-
}
3846

3947
r := getRepo(false)
4048
req := core.NewDatasetRequests(r, nil)
4149

50+
dsr, err := repo.ParseDatasetRef(args[0])
51+
ExitIfErr(err)
52+
4253
p := &core.GetDatasetParams{
43-
Name: args[0],
44-
Path: datastore.NewKey(args[0]),
54+
Name: dsr.Name,
55+
Path: dsr.Path,
4556
}
4657
res := &repo.DatasetRef{}
47-
err := req.Get(p, res)
58+
err = req.Get(p, res)
4859
ExitIfErr(err)
4960

5061
ds := res.Dataset
5162

52-
if cmd.Flag("data-only").Value.String() == "true" {
53-
src, err := dsfs.LoadData(r.Store(), ds)
63+
if cmd.Flag("zip").Value.String() == "true" {
64+
dst, err := os.Create(fmt.Sprintf("%s.zip", path))
5465
ExitIfErr(err)
5566

56-
dst, err := os.Create(fmt.Sprintf("%s.%s", path, ds.Structure.Format.String()))
67+
err = dsutil.WriteZipArchive(r.Store(), ds, dst)
68+
ExitIfErr(err)
69+
err = dst.Close()
5770
ExitIfErr(err)
71+
return
72+
} else if cmd.Flag("dataset").Value.String() == "true" {
73+
exportCmdData = true
74+
exportCmdMeta = true
75+
exportCmdStructure = true
76+
}
5877

59-
_, err = io.Copy(dst, src)
78+
if path != "" {
79+
err = os.MkdirAll(path, os.ModePerm)
6080
ExitIfErr(err)
81+
}
6182

62-
err = dst.Close()
83+
if exportCmdMeta {
84+
var md interface{}
85+
// TODO - this ensures a "form" metadata file is written
86+
// when one doesn't exist. This should be better
87+
if ds.Meta.IsEmpty() {
88+
md = struct {
89+
// Url to access the dataset
90+
AccessPath string `json:"accessPath"`
91+
// The frequency with which dataset changes. Must be an ISO 8601 repeating duration
92+
AccrualPeriodicity string `json:"accrualPeriodicity"`
93+
// Citations is a slice of assets used to build this dataset
94+
Citations []string `json:"citations"`
95+
// Contribute
96+
// Contributors []stirng `json:"contributors"`
97+
// Description follows the DCAT sense of the word, it should be around a paragraph of
98+
// human-readable text
99+
Description string `json:"description"`
100+
// Url that should / must lead directly to the data itself
101+
DownloadPath string `json:"downloadPath"`
102+
// HomePath is a path to a "home" resource, either a url or d.web path
103+
HomePath string `json:"homePath"`
104+
// Identifier is for *other* data catalog specifications. Identifier should not be used
105+
// or relied on to be unique, because this package does not enforce any of these rules.
106+
Identifier string `json:"identifier"`
107+
// String of Keywords
108+
Keywords []string `json:"keywords"`
109+
// Languages this dataset is written in
110+
Language []string `json:"language"`
111+
// License will automatically parse to & from a string value if provided as a raw string
112+
License string `json:"license"`
113+
// Kind is required, must be qri:md:[version]
114+
Qri dataset.Kind `json:"qri"`
115+
// path to readmePath
116+
ReadmePath string `json:"readmePath"`
117+
// Title of this dataset
118+
Title string `json:"title"`
119+
// Theme
120+
Theme []string `json:"theme"`
121+
// Version is the semantic version for this dataset
122+
Version string `json:"version"`
123+
}{
124+
Qri: dataset.KindMeta,
125+
}
126+
} else {
127+
md = ds.Meta
128+
}
129+
130+
metaPath := filepath.Join(path, dsfs.PackageFileMeta.Filename())
131+
mdBytes, err := json.MarshalIndent(md, "", " ")
132+
err = ioutil.WriteFile(metaPath, mdBytes, os.ModePerm)
63133
ExitIfErr(err)
64-
return
134+
printSuccess("exported metadata file to: %s", metaPath)
65135
}
66136

67-
if cmd.Flag("zip").Value.String() == "true" {
68-
dst, err := os.Create(fmt.Sprintf("%s.zip", path))
137+
if exportCmdStructure {
138+
stpath := filepath.Join(path, dsfs.PackageFileStructure.Filename())
139+
stbytes, err := json.MarshalIndent(ds.Structure, "", " ")
140+
err = ioutil.WriteFile(stpath, stbytes, os.ModePerm)
141+
ExitIfErr(err)
142+
printSuccess("exported structure file to: %s", stpath)
143+
}
144+
145+
if exportCmdData {
146+
src, err := dsfs.LoadData(r.Store(), ds)
69147
ExitIfErr(err)
70148

71-
err = dsutil.WriteZipArchive(r.Store(), ds, dst)
149+
dataPath := filepath.Join(path, fmt.Sprintf("data.%s", ds.Structure.Format.String()))
150+
dst, err := os.Create(dataPath)
72151
ExitIfErr(err)
152+
153+
_, err = io.Copy(dst, src)
154+
ExitIfErr(err)
155+
73156
err = dst.Close()
74157
ExitIfErr(err)
75-
return
158+
printSuccess("exported dataset data to: %s", dataPath)
76159
}
77160

78-
err = dsutil.WriteDir(r.Store(), ds, path)
79-
ExitIfErr(err)
161+
// err = dsutil.WriteDir(r.Store(), ds, path)
162+
// ExitIfErr(err)
80163
},
81164
}
82165

83166
func init() {
84167
RootCmd.AddCommand(exportCmd)
85-
exportCmd.Flags().StringP("output", "o", "dataset", "path to write to")
86-
exportCmd.Flags().BoolP("data-only", "d", false, "write data only (no package)")
168+
exportCmd.Flags().StringP("output", "o", "", "path to write to, default is current directory")
87169
exportCmd.Flags().BoolP("zip", "z", false, "compress export as zip archive")
170+
exportCmd.Flags().BoolVarP(&exportCmdDataset, "dataset", "", false, "export full dataset package")
171+
exportCmd.Flags().BoolVarP(&exportCmdMeta, "meta", "m", false, "export dataset metadata file")
172+
exportCmd.Flags().BoolVarP(&exportCmdStructure, "structure", "s", false, "export dataset structure file")
173+
exportCmd.Flags().BoolVarP(&exportCmdData, "data", "d", true, "export dataset data file")
174+
// exportCmd.Flags().BoolVarP(&exportCmdTransform, "transform", "t", false, "export dataset transform file")
175+
// exportCmd.Flags().BoolVarP(&exportCmdVis, "vis-conf", "z", false, "export viz config file")
176+
88177
// TODO - get format conversion up & running
89178
// exportCmd.Flags().StringP("format", "f", "csv", "set output format [csv,json]")
90179
}

0 commit comments

Comments
 (0)