diff --git a/Makefile.am b/Makefile.am index 629276d..1997d4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -248,8 +248,9 @@ clean-local: rm -rf autom4te.cache rm -f cmd/mstored/istored rm -f cmd/mstorectl/mstorectl - rm -rf tmp/ +# rm -rf tmp/ distclean-local: rm -rf autom4te.cache rm -rf $(DIST_DIR) + rm -rf tmp/ diff --git a/Makefile.in b/Makefile.in index f4e25ec..4857aaf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1043,11 +1043,12 @@ clean-local: rm -rf autom4te.cache rm -f cmd/mstored/istored rm -f cmd/mstorectl/mstorectl - rm -rf tmp/ +# rm -rf tmp/ distclean-local: rm -rf autom4te.cache rm -rf $(DIST_DIR) + rm -rf tmp/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/cmd/mstorectl/filecmd.go b/cmd/mstorectl/filecmd.go index 72b41b5..7aad96d 100644 --- a/cmd/mstorectl/filecmd.go +++ b/cmd/mstorectl/filecmd.go @@ -15,6 +15,8 @@ import ( "fmt" "io/fs" "net/url" + "os" + "path" "path/filepath" "slices" "strings" @@ -101,6 +103,18 @@ func (util *FileUtil) CreateFileCmds() *cobra.Command { } subCmd.AddCommand(importFilesCmd) + // ExportFiles + var exportFilesCmd = &cobra.Command{ + Use: "export directory [user:pass@]hostname[:port]/collection dir", + Args: cobra.ExactArgs(2), + Short: "Download file tree to storage as is", + Run: util.ExportFiles, + } + exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.Detail, "detail", "D", false, "Show detail file information") + exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.AsPrefix, "asprefix", "P", true, "Use path as collection path prefix") + exportFilesCmd.Flags().BoolVarP(&util.exportFilesParams.AsRegexp, "asregex", "R", false, "Use path as collection path prefix") + subCmd.AddCommand(exportFilesCmd) + return subCmd } @@ -152,6 +166,7 @@ type FileUtil struct { deleteFileParams DeleteFileParams listFilesParams ListFilesParams importFilesParams ImportFilesParams + exportFilesParams ExportFilesParams listCollectionsParams ListCollectionsParams deleteCollectionParams DeleteCollectionParams commonFileParams CommonFileParams @@ -411,6 +426,96 @@ func (util *FileUtil) importFiles(common *CommonFileParams, params *ImportFilesP return res, err } +// ExportFiles +type ExportFilesParams struct { + Filepath string + Detail bool + AsPrefix bool + AsRegexp bool + Dest string +} + +type ExportFilesResult struct { + Files []descr.File `yaml:"files,omitempty"` + Filenames []string `yaml:"filenames,omitempty"` +} + +func (util *FileUtil) ExportFiles(cmd *cobra.Command, args []string) { + util.exportFilesParams.Filepath = args[0] + util.exportFilesParams.Dest = args[1] + res, err := util.exportFiles(&util.commonFileParams, &util.exportFilesParams) + printResponse(res, err) +} +func (util *FileUtil) exportFiles(common *CommonFileParams, params *ExportFilesParams) (*ExportFilesResult, error) { + var err error + res := &ExportFilesResult{} + params.Filepath, err = packUserinfo(params.Filepath, common.Username, common.Password) + if err != nil { + return res, err + } + if params.AsRegexp { + params.AsPrefix = false + } + var pathAs terms.PathUsage + switch { + case params.AsRegexp: + pathAs = terms.AsRegexp + case params.AsPrefix: + pathAs = terms.AsPrefix + default: + pathAs = terms.AsFinePath + } + timeout := time.Duration(common.Timeout) * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + files, err := client.NewClient().ListFiles(ctx, params.Filepath, pathAs) + if err != nil { + return res, err + } + + exportedFiles := make([]descr.File, 0) + for _, file := range files { + destdir := filepath.Join(params.Dest, file.Collection) + err = os.MkdirAll(destdir, 0750) + if err != nil { + return res, err + } + srcpath, err := makeFileURI(params.Filepath, file.Collection, file.Name) + if err != nil { + return res, err + } + destpath := filepath.Join(params.Dest, file.Collection, file.Name) + timeout := time.Duration(common.Timeout) * time.Second + ctx, _ := context.WithTimeout(context.Background(), timeout) + _, err = client.NewClient().GetFile(ctx, srcpath, destpath) + if err != nil { + fmt.Printf("- %s: error %v\n", srcpath, err) + //return res, err + err = nil + } else { + fmt.Printf("- %s: ok\n", srcpath) + exportedFiles = append(exportedFiles, file) + } + } + if params.Detail { + res.Files = exportedFiles + } else { + res.Filenames = makeFilelistFromFiles(exportedFiles) + } + return res, err +} + +func makeFileURI(hosturi, collection, name string) (string, error) { + var err error + var res string + uri, err := url.Parse(hosturi) + if err != nil { + return res, err + } + uri.Path = path.Join(collection, name) + res = uri.String() + return res, err +} + // ListCollections type ListCollectionsParams struct { Path string