Skip to content

Commit bb84f64

Browse files
committed
cmd: add walk subcmd
1 parent 1170c39 commit bb84f64

2 files changed

Lines changed: 119 additions & 0 deletions

File tree

cmd/mypan/main.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,25 @@ func (myApp MyApp) Run(args []string) error {
455455
return myApp.syncAction(cCtx, src, dst, false)
456456
},
457457
},
458+
{
459+
Name: "walk",
460+
Flags: []cli.Flag{
461+
&cli.IntFlag{Name: "parallel", Aliases: []string{"p"}},
462+
},
463+
ArgsUsage: "remotepath argv...",
464+
Action: func(cCtx *cli.Context) error {
465+
src := cCtx.Args().Get(0)
466+
argv := cCtx.Args().Tail()
467+
if len(argv) == 0 {
468+
return cli.Exit("argv is required", 1)
469+
}
470+
w := NewWalker(myApp.dstClient, argv)
471+
if p := cCtx.Int("parallel"); p > 1 {
472+
w.Parallel(p)
473+
}
474+
return w.Walk(myApp.ctx, src)
475+
},
476+
},
458477
{
459478
Name: "rename",
460479
ArgsUsage: "remotepath newname",

cmd/mypan/walk.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"os/exec"
7+
8+
"mypan/pkg/client"
9+
"mypan/pkg/util"
10+
11+
"github.com/pkg/errors"
12+
)
13+
14+
type WalkerStdin struct {
15+
Path string `json:"path"`
16+
IsDir int `json:"isdir"`
17+
18+
Size uint64 `json:"size"`
19+
ServerCtime uint64 `json:"server_ctime"`
20+
ServerMtime uint64 `json:"server_mtime"`
21+
LocalCtime uint64 `json:"local_ctime"`
22+
LocalMtime uint64 `json:"local_mtime"`
23+
}
24+
25+
type Walker struct {
26+
client client.ClientI
27+
execArgv []string
28+
29+
parallelDo *util.ParallelDo
30+
}
31+
32+
func NewWalker(
33+
client client.ClientI,
34+
execArgv []string,
35+
) *Walker {
36+
w := &Walker{
37+
client: client,
38+
execArgv: execArgv,
39+
}
40+
return w
41+
}
42+
43+
func (w *Walker) Parallel(n int) {
44+
w.parallelDo = util.NewParallelDo(n)
45+
}
46+
47+
func (w *Walker) Walk(ctx context.Context, dir string) error {
48+
if err := w.exec(ctx, &WalkerStdin{
49+
Path: dir,
50+
IsDir: 1,
51+
}); err != nil {
52+
return err
53+
}
54+
resp, err := w.client.ListEx(ctx, dir)
55+
if err != nil {
56+
return errors.Wrapf(err, "list %s", dir)
57+
}
58+
for _, src := range resp.List {
59+
if src.IsDir != 0 {
60+
// we check src.Empty by ourselves
61+
err := w.Walk(ctx, src.Path)
62+
if err != nil {
63+
return err
64+
}
65+
} else {
66+
err := w.exec(ctx, &WalkerStdin{
67+
Path: src.Path,
68+
IsDir: src.IsDir,
69+
70+
Size: src.Size,
71+
ServerCtime: src.ServerCtime,
72+
ServerMtime: src.ServerMtime,
73+
LocalCtime: src.LocalCtime,
74+
LocalMtime: src.LocalMtime,
75+
})
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
}
81+
return util.TryParallelJoin(ctx, w.parallelDo)
82+
}
83+
84+
func (w *Walker) exec(ctx context.Context, stdin *WalkerStdin) error {
85+
return util.TryParallelDo(ctx, w.parallelDo, func(ctx context.Context) error {
86+
return w.exec_(ctx, stdin)
87+
})
88+
}
89+
90+
func (w *Walker) exec_(ctx context.Context, stdin *WalkerStdin) error {
91+
stdinData := util.MustMarshalJSON(stdin)
92+
stdinReader := bytes.NewBuffer(stdinData)
93+
cmd := exec.CommandContext(ctx, w.execArgv[0], w.execArgv[1:]...)
94+
cmd.Stdin = stdinReader
95+
output, err := cmd.CombinedOutput()
96+
if err != nil {
97+
return errors.Wrapf(err, "exec for %s: %s", stdin.Path, output)
98+
}
99+
return nil
100+
}

0 commit comments

Comments
 (0)