Skip to content

Commit

Permalink
feat: new export command.
Browse files Browse the repository at this point in the history
export now follows our new command conventions
  • Loading branch information
b5 committed Jan 25, 2018
1 parent cae7dbd commit f36da26
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 23 deletions.
2 changes: 1 addition & 1 deletion cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestCommandsIntegration(t *testing.T) {
{"list"},
{"save", "-f" + movies2FilePath, "-n" + "movies", "-m" + "commit_1"},
{"log", "-n" + "movies"},
// {"run", "select * from movies limit 5"},
{"export", "--dataset", "movies", "-o" + path},
{"rename", "movies", "movie"},
{"validate", "-n" + "movie"},
{"remove", "movie"},
Expand Down
133 changes: 111 additions & 22 deletions cmd/export.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package cmd

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"

"github.com/ipfs/go-datastore"
"github.com/qri-io/dataset"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/dataset/dsutil"
"github.com/qri-io/qri/core"
"github.com/qri-io/qri/repo"
"github.com/spf13/cobra"
)

var (
exportCmdDataset bool
exportCmdMeta bool
exportCmdStructure bool
exportCmdData bool
exportCmdTransform bool
exportCmdVis bool
)

// exportCmd represents the export command
var exportCmd = &cobra.Command{
Use: "export",
Expand All @@ -31,60 +43,137 @@ To export everything about a dataset, use the --dataset flag.`,
return
}
path := cmd.Flag("output").Value.String()
if path == "" {
// TODO - support printing to stdout
ErrExit(fmt.Errorf("please specify an output path"))
}

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

dsr, err := repo.ParseDatasetRef(args[0])
ExitIfErr(err)

p := &core.GetDatasetParams{
Name: args[0],
Path: datastore.NewKey(args[0]),
Name: dsr.Name,
Path: dsr.Path,
}
res := &repo.DatasetRef{}
err := req.Get(p, res)
err = req.Get(p, res)
ExitIfErr(err)

ds := res.Dataset

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

dst, err := os.Create(fmt.Sprintf("%s.%s", path, ds.Structure.Format.String()))
err = dsutil.WriteZipArchive(r.Store(), ds, dst)
ExitIfErr(err)
err = dst.Close()
ExitIfErr(err)
return
} else if cmd.Flag("dataset").Value.String() == "true" {
exportCmdData = true
exportCmdMeta = true
exportCmdStructure = true
}

_, err = io.Copy(dst, src)
if path != "" {
err = os.MkdirAll(path, os.ModePerm)
ExitIfErr(err)
}

err = dst.Close()
if exportCmdMeta {
var md interface{}
// TODO - this ensures a "form" metadata file is written
// when one doesn't exist. This should be better
if ds.Meta.IsEmpty() {
md = struct {
// Url to access the dataset
AccessPath string `json:"accessPath"`
// The frequency with which dataset changes. Must be an ISO 8601 repeating duration
AccrualPeriodicity string `json:"accrualPeriodicity"`
// Citations is a slice of assets used to build this dataset
Citations []string `json:"citations"`
// Contribute
// Contributors []stirng `json:"contributors"`
// Description follows the DCAT sense of the word, it should be around a paragraph of
// human-readable text
Description string `json:"description"`
// Url that should / must lead directly to the data itself
DownloadPath string `json:"downloadPath"`
// HomePath is a path to a "home" resource, either a url or d.web path
HomePath string `json:"homePath"`
// Identifier is for *other* data catalog specifications. Identifier should not be used
// or relied on to be unique, because this package does not enforce any of these rules.
Identifier string `json:"identifier"`
// String of Keywords
Keywords []string `json:"keywords"`
// Languages this dataset is written in
Language []string `json:"language"`
// License will automatically parse to & from a string value if provided as a raw string
License string `json:"license"`
// Kind is required, must be qri:md:[version]
Qri dataset.Kind `json:"qri"`
// path to readmePath
ReadmePath string `json:"readmePath"`
// Title of this dataset
Title string `json:"title"`
// Theme
Theme []string `json:"theme"`
// Version is the semantic version for this dataset
Version string `json:"version"`
}{
Qri: dataset.KindMeta,
}
} else {
md = ds.Meta
}

metaPath := filepath.Join(path, dsfs.PackageFileMeta.Filename())
mdBytes, err := json.MarshalIndent(md, "", " ")
err = ioutil.WriteFile(metaPath, mdBytes, os.ModePerm)
ExitIfErr(err)
return
printSuccess("exported metadata file to: %s", metaPath)
}

if cmd.Flag("zip").Value.String() == "true" {
dst, err := os.Create(fmt.Sprintf("%s.zip", path))
if exportCmdStructure {
stpath := filepath.Join(path, dsfs.PackageFileStructure.Filename())
stbytes, err := json.MarshalIndent(ds.Structure, "", " ")
err = ioutil.WriteFile(stpath, stbytes, os.ModePerm)
ExitIfErr(err)
printSuccess("exported structure file to: %s", stpath)
}

if exportCmdData {
src, err := dsfs.LoadData(r.Store(), ds)
ExitIfErr(err)

err = dsutil.WriteZipArchive(r.Store(), ds, dst)
dataPath := filepath.Join(path, fmt.Sprintf("data.%s", ds.Structure.Format.String()))
dst, err := os.Create(dataPath)
ExitIfErr(err)

_, err = io.Copy(dst, src)
ExitIfErr(err)

err = dst.Close()
ExitIfErr(err)
return
printSuccess("exported dataset data to: %s", dataPath)
}

err = dsutil.WriteDir(r.Store(), ds, path)
ExitIfErr(err)
// err = dsutil.WriteDir(r.Store(), ds, path)
// ExitIfErr(err)
},
}

func init() {
RootCmd.AddCommand(exportCmd)
exportCmd.Flags().StringP("output", "o", "dataset", "path to write to")
exportCmd.Flags().BoolP("data-only", "d", false, "write data only (no package)")
exportCmd.Flags().StringP("output", "o", "", "path to write to, default is current directory")
exportCmd.Flags().BoolP("zip", "z", false, "compress export as zip archive")
exportCmd.Flags().BoolVarP(&exportCmdDataset, "dataset", "", false, "export full dataset package")
exportCmd.Flags().BoolVarP(&exportCmdMeta, "meta", "m", false, "export dataset metadata file")
exportCmd.Flags().BoolVarP(&exportCmdStructure, "structure", "s", false, "export dataset structure file")
exportCmd.Flags().BoolVarP(&exportCmdData, "data", "d", true, "export dataset data file")
// exportCmd.Flags().BoolVarP(&exportCmdTransform, "transform", "t", false, "export dataset transform file")
// exportCmd.Flags().BoolVarP(&exportCmdVis, "vis-conf", "z", false, "export viz config file")

// TODO - get format conversion up & running
// exportCmd.Flags().StringP("format", "f", "csv", "set output format [csv,json]")
}

0 comments on commit f36da26

Please sign in to comment.