diff --git a/internal/slicer/slicer.go b/internal/slicer/slicer.go index ce791162..51d8e195 100644 --- a/internal/slicer/slicer.go +++ b/internal/slicer/slicer.go @@ -90,6 +90,18 @@ func Run(options *RunOptions) error { targetDir = filepath.Join(dir, targetDir) } + // Check the target directory before fetching any packages, so that the + // error names it instead of surfacing later while extracting a package. + targetInfo, err := os.Stat(targetDir) + if os.IsNotExist(err) { + return fmt.Errorf("target directory does not exist: %s", targetDir) + } else if err != nil { + return err + } + if !targetInfo.IsDir() { + return fmt.Errorf("target is not a directory: %s", targetDir) + } + pkgArchive, err := selectPkgArchives(options.Archives, options.Selection) if err != nil { return err diff --git a/internal/slicer/slicer_test.go b/internal/slicer/slicer_test.go index d6ef9ca0..f5d24c19 100644 --- a/internal/slicer/slicer_test.go +++ b/internal/slicer/slicer_test.go @@ -634,6 +634,40 @@ var slicerTests = []slicerTest{{ opts.TargetDir, err = filepath.Rel(dir, opts.TargetDir) c.Assert(err, IsNil) }, +}, { + summary: "Target directory must exist", + slices: []setup.SliceKey{{"test-package", "myslice"}}, + release: map[string]string{ + "slices/mydir/test-package.yaml": ` + package: test-package + slices: + myslice: + contents: + /dir/file: + `, + }, + hackopt: func(c *C, opts *slicer.RunOptions) { + opts.TargetDir = filepath.Join(opts.TargetDir, "missing") + }, + error: `target directory does not exist: .*/missing`, +}, { + summary: "Target directory must be a directory", + slices: []setup.SliceKey{{"test-package", "myslice"}}, + release: map[string]string{ + "slices/mydir/test-package.yaml": ` + package: test-package + slices: + myslice: + contents: + /dir/file: + `, + }, + hackopt: func(c *C, opts *slicer.RunOptions) { + opts.TargetDir = filepath.Join(opts.TargetDir, "file") + err := os.WriteFile(opts.TargetDir, nil, 0644) + c.Assert(err, IsNil) + }, + error: `target is not a directory: .*/file`, }, { summary: "Can list parent directories of normal paths", slices: []setup.SliceKey{{"test-package", "myslice"}},