diff --git a/cmd/fsi_integration_test.go b/cmd/fsi_integration_test.go index 7ba13cd9f..922336f6c 100644 --- a/cmd/fsi_integration_test.go +++ b/cmd/fsi_integration_test.go @@ -904,6 +904,47 @@ run ` + "`qri save`" + ` to commit this dataset } } +// Test init with a directory will create that directory +func TestInitWithDirectory(t *testing.T) { + fr := NewFSITestRunner(t, "qri_test_init_with_directory") + defer fr.Delete() + + fr.ChdirToRoot() + + // Init with a directory to create. + if err := fr.ExecCommand(fmt.Sprintf("qri init init_dir --name init_dir --format csv")); err != nil { + t.Fatalf(err.Error()) + } + + // Directory has been created by `qri init` + workDir := fr.ChdirToWorkDir("init_dir") + + // Verify the directory contains the files that we expect. + dirContents := listDirectory(workDir) + expectContents := []string{".qri-ref", "body.csv", "meta.json", "schema.json"} + if diff := cmp.Diff(dirContents, expectContents); diff != "" { + t.Errorf("directory contents (-want +got):\n%s", diff) + } + + // Status, check that the working directory has added files. + if err := fr.ExecCommand("qri status"); err != nil { + t.Fatalf(err.Error()) + } + + output := fr.GetCommandOutput() + expect := `for linked dataset [test_peer/init_dir] + + add: meta (source: meta.json) + add: schema (source: schema.json) + add: body (source: body.csv) + +run ` + "`qri save`" + ` to commit this dataset +` + if diff := cmpTextLines(expect, output); diff != "" { + t.Errorf("qri status (-want +got):\n%s", diff) + } +} + func parseRefFromSave(output string) string { pos := strings.Index(output, "saved: ") ref := output[pos+7:] diff --git a/cmd/init.go b/cmd/init.go index a4079ac72..947786b74 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -23,7 +23,9 @@ func NewInitCommand(f Factory, ioStreams ioes.IOStreams) *cobra.Command { "group": "dataset", }, RunE: func(cmd *cobra.Command, args []string) error { - o.Complete(f) + if err := o.Complete(f, args); err != nil { + return err + } return o.Run() }, } @@ -42,17 +44,21 @@ type InitOptions struct { Name string Format string SourceBodyPath string + Mkdir string DatasetRequests *lib.DatasetRequests FSIMethods *lib.FSIMethods } // Complete completes a dataset reference -func (o *InitOptions) Complete(f Factory) (err error) { +func (o *InitOptions) Complete(f Factory, args []string) (err error) { if o.DatasetRequests, err = f.DatasetRequests(); err != nil { return err } o.FSIMethods, err = f.FSIMethods() + if len(args) > 0 && args[0] != "." { + o.Mkdir = args[0] + } return err } @@ -63,9 +69,14 @@ func (o *InitOptions) Run() (err error) { return err } - // Suggestion for the dataset name defaults to the name of the current directory. + // Suggestion for the dataset name defaults to directory it is being linked into if o.Name == "" { - suggestedName := varName.CreateVarNameFromString(filepath.Base(pwd)) + var suggestedName string + if o.Mkdir == "" { + suggestedName = varName.CreateVarNameFromString(filepath.Base(pwd)) + } else { + suggestedName = varName.CreateVarNameFromString(o.Mkdir) + } o.Name = inputText(o.ErrOut, o.In, "Name of new dataset", suggestedName) } @@ -75,6 +86,7 @@ func (o *InitOptions) Run() (err error) { p := &lib.InitFSIDatasetParams{ Dir: pwd, + Mkdir: o.Mkdir, Format: o.Format, Name: o.Name, SourceBodyPath: o.SourceBodyPath, diff --git a/fsi/init.go b/fsi/init.go index 43d2b31c3..86d8f2959 100644 --- a/fsi/init.go +++ b/fsi/init.go @@ -15,6 +15,7 @@ type InitParams struct { Dir string Name string Format string + Mkdir string SourceBodyPath string } @@ -30,7 +31,22 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) { return "", fmt.Errorf("invalid path to initialize. '%s' is not a directory", p.Dir) } - if err = canInitDir(p.Dir); err != nil { + // TODO(dlong): This function should more closely resemble Checkout in lib/fsi.go + + // Either use an existing directory, or create one at the given directory. + var targetPath string + if p.Mkdir == "" { + targetPath = p.Dir + } else { + targetPath = filepath.Join(p.Dir, p.Mkdir) + // Create the directory. It is not an error for the directory to already exist, as long + // as it is not already linked, which is checked below. + if err := os.Mkdir(targetPath, os.ModePerm); err != nil { + return "", err + } + } + + if err = canInitDir(targetPath); err != nil { return "", err } @@ -57,7 +73,7 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) { } // Create the link file, containing the dataset reference. - if name, err = fsi.CreateLink(p.Dir, ref.AliasString()); err != nil { + if name, err = fsi.CreateLink(targetPath, ref.AliasString()); err != nil { return name, err } @@ -69,7 +85,7 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) { "homeURL": "" } `) - if err := ioutil.WriteFile(filepath.Join(p.Dir, "meta.json"), metaSkeleton, os.ModePerm); err != nil { + if err := ioutil.WriteFile(filepath.Join(targetPath, "meta.json"), metaSkeleton, os.ModePerm); err != nil { return name, err } @@ -107,7 +123,7 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) { } } data, err = json.MarshalIndent(schema, "", " ") - if err := ioutil.WriteFile(filepath.Join(p.Dir, "schema.json"), data, os.ModePerm); err != nil { + if err := ioutil.WriteFile(filepath.Join(targetPath, "schema.json"), data, os.ModePerm); err != nil { return name, err } @@ -129,7 +145,7 @@ func (fsi *FSI) InitDataset(p InitParams) (name string, err error) { return "", err } } - bodyFilename := filepath.Join(p.Dir, fmt.Sprintf("body.%s", p.Format)) + bodyFilename := filepath.Join(targetPath, fmt.Sprintf("body.%s", p.Format)) if err := ioutil.WriteFile(bodyFilename, bodyBytes, os.ModePerm); err != nil { return "", err }