package putp import ( "fmt" "os" "path" "path/filepath" "strconv" "strings" "time" "github.com/inhies/go-bytesize" "github.com/spf13/cobra" "gitlink.org.cn/cloudream/common/pkgs/iterator" "gitlink.org.cn/cloudream/common/sdks" cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" "gitlink.org.cn/cloudream/jcs-pub/common/ecode" "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd" ) func init() { var opt option c := &cobra.Command{ Use: "putp /", Short: "upload local files to a package", Args: cobra.ExactArgs(2), RunE: func(c *cobra.Command, args []string) error { ctx := cmd.GetCmdCtx(c) return putp(c, ctx, opt, args) }, } c.Flags().BoolVar(&opt.UseID, "id", false, "treat the second argument as package id") c.Flags().StringVar(&opt.Prefix, "prefix", "", "add prefix to every uploaded file") c.Flags().BoolVar(&opt.Create, "create", false, "create package if not exists") c.Flags().Int64Var(&opt.Affinity, "affinity", 0, "affinity user space of the package") cmd.RootCmd.AddCommand(c) } type option struct { UseID bool Prefix string Create bool Affinity int64 } func putp(c *cobra.Command, ctx *cmd.CommandContext, opt option, args []string) error { absLocal, err := filepath.Abs(args[0]) if err != nil { return err } local, err := os.Stat(absLocal) if err != nil { return err } var pkgID clitypes.PackageID if opt.UseID { id, err := strconv.ParseInt(args[1], 10, 64) if err != nil { return err } pkgID = clitypes.PackageID(id) _, err = ctx.Client.Package().Get(cliapi.PackageGet{ PackageID: pkgID, }) if err != nil { return err } } else { comps := strings.Split(args[1], "/") if len(comps) != 2 { return fmt.Errorf("invalid package name") } pkg, err := ctx.Client.Package().GetByFullName(cliapi.PackageGetByFullName{ BucketName: comps[0], PackageName: comps[1], }) if err != nil { if !sdks.IsErrorCode(err, string(ecode.DataNotFound)) { return err } if !opt.Create { return fmt.Errorf("package not found") } bkt, err := ctx.Client.Bucket().GetByName(cliapi.BucketGetByName{ Name: comps[0], }) if err != nil { return fmt.Errorf("get bucket %v: %w", comps[0], err) } cpkg, err := ctx.Client.Package().Create(cliapi.PackageCreate{ BucketID: bkt.Bucket.BucketID, Name: comps[1], }) if err != nil { return fmt.Errorf("create package %v: %w", args[1], err) } pkgID = cpkg.Package.PackageID } else { pkgID = pkg.Package.PackageID } } if !local.IsDir() { file, err := os.Open(absLocal) if err != nil { return err } defer file.Close() info, err := file.Stat() if err != nil { return err } pat := filepath.Base(absLocal) if opt.Prefix != "" { pat = path.Join(opt.Prefix, pat) } fmt.Printf("%v\n", pat) startTime := time.Now() _, err = ctx.Client.Object().Upload(cliapi.ObjectUpload{ Info: cliapi.ObjectUploadInfo{ PackageID: pkgID, Affinity: clitypes.UserSpaceID(opt.Affinity), }, Files: iterator.Array(&cliapi.UploadingObject{ Path: pat, File: file, }), }) if err != nil { return fmt.Errorf("upload file %v: %w", pat, err) } dt := time.Since(startTime) fmt.Printf("size: %v, time: %v, speed: %v/s\n", bytesize.ByteSize(info.Size()), dt, bytesize.ByteSize(int64(float64(info.Size())/dt.Seconds()))) return nil } iter := &FileIterator{ absRootPath: absLocal, jpathRoot: clitypes.PathFromJcsPathString(opt.Prefix), } startTime := time.Now() _, err = ctx.Client.Object().Upload(cliapi.ObjectUpload{ Info: cliapi.ObjectUploadInfo{ PackageID: pkgID, Affinity: clitypes.UserSpaceID(opt.Affinity), }, Files: iter, }) if err != nil { if !iter.lastStartTime.IsZero() { fmt.Printf("\tx\n") } return fmt.Errorf("upload files: %w", err) } dt := time.Since(startTime) if !iter.lastStartTime.IsZero() { fileDt := time.Since(iter.lastStartTime) fmt.Printf("\t%v\n", fileDt) } fmt.Printf("%v files, total size: %v, time: %v, speed: %v/s\n", iter.fileCount, bytesize.ByteSize(iter.totalSize), dt, bytesize.ByteSize(int64(float64(iter.totalSize)/dt.Seconds()))) return nil }