diff --git a/cmd/acp-rewrite/main.go b/cmd/acp-rewrite/main.go index bcfe2d1..be9f189 100644 --- a/cmd/acp-rewrite/main.go +++ b/cmd/acp-rewrite/main.go @@ -10,7 +10,6 @@ import ( "math/rand" "os" "os/signal" - "path" "path/filepath" "sort" "strings" @@ -519,8 +518,7 @@ func removeTmp(tmpFiles []string, tmp string) []string { func findJob(report *acp.Report, filePath string) (*acp.Job, bool) { for _, job := range report.Jobs { - full := job.Base + path.Join(job.Path...) - if full == filePath { + if job.FullPath == filePath { return job, true } } @@ -557,8 +555,7 @@ func mergeReport(jobs map[string]*acp.Job, errors *[]*acp.Error, report *acp.Rep return } for _, job := range report.Jobs { - full := job.Base + path.Join(job.Path...) - jobs[full] = job + jobs[job.FullPath] = job } if len(report.Errors) > 0 { *errors = append(*errors, report.Errors...) @@ -603,9 +600,8 @@ func printDuplicates(jobs map[string]*acp.Job) { if job == nil || job.SHA256 == "" || job.Size == 0 { continue } - full := job.Base + path.Join(job.Path...) key := dupKey{size: job.Size, hash: job.SHA256} - dups[key] = append(dups[key], full) + dups[key] = append(dups[key], job.FullPath) } keys := make([]dupKey, 0, len(dups)) diff --git a/go.mod b/go.mod index 81428fa..9750287 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/samuelncui/godf v0.0.0-20231004032257-e436410ad5a0 github.com/schollz/progressbar/v3 v3.13.1 github.com/sirupsen/logrus v1.9.3 + golang.org/x/sys v0.12.0 ) require ( @@ -22,6 +23,5 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/rivo/uniseg v0.4.4 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.12.0 // indirect golang.org/x/term v0.12.0 // indirect ) diff --git a/index.go b/index.go index 52f9eee..8ffaab7 100644 --- a/index.go +++ b/index.go @@ -8,8 +8,6 @@ import ( "strings" "sync/atomic" "time" - - "github.com/samber/lo" ) const ( @@ -162,7 +160,7 @@ func (c *Copyer) walk(ctx context.Context) ([]*baseJob, error) { appendJob(&baseJob{ copyer: c, - src: &source{base: "/", path: lo.Filter(strings.Split(j.src, "/"), func(s string, _ int) bool { return s != "" })}, + src: &source{base: "/", path: j.src}, path: j.src, stat: stat, targets: j.dsts, @@ -175,13 +173,14 @@ func (c *Copyer) walk(ctx context.Context) ([]*baseJob, error) { func (c *Copyer) joinJobs(jobs []*baseJob) ([]*baseJob, error) { sort.Slice(jobs, func(i int, j int) bool { - return comparePath(jobs[i].src.path, jobs[j].src.path) < 0 + si, sj := strings.ReplaceAll(jobs[i].src.path, "/", "\x00"), strings.ReplaceAll(jobs[j].src.path, "/", "\x00") + return si < sj }) var last *baseJob filtered := make([]*baseJob, 0, len(jobs)) for _, job := range jobs { - if last != nil && comparePath(last.src.path, job.src.path) == 0 { + if last != nil && last.src.path == job.src.path { c.reportError(last.path, "", fmt.Errorf("same relative path, ignored, '%s'", job.path)) continue } diff --git a/job.go b/job.go index 17634e3..d6da7fc 100644 --- a/job.go +++ b/job.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "io" "io/fs" + "path" "sync" "time" ) @@ -92,8 +93,9 @@ func (j *baseJob) fail(path string, err error) { func (j *baseJob) report() *Job { return &Job{ - Base: j.src.base, - Path: j.src.path, + FullPath: path.Join(j.src.base, j.src.path), + Base: j.src.base, + Path: j.src.path, Status: statusMapping[j.status], SuccessTargets: j.successTargets, @@ -142,8 +144,9 @@ func (wj *writeJob) wait() { } type Job struct { - Base string `json:"base"` - Path []string `json:"path"` + FullPath string `json:"full_path"` + Base string `json:"base"` + Path string `json:"path"` Status string `json:"status"` SuccessTargets []string `json:"success_target,omitempty"` diff --git a/opt.go b/opt.go index 3dd5989..50f46f9 100644 --- a/opt.go +++ b/opt.go @@ -9,23 +9,19 @@ import ( type source struct { base string - path []string + path string } func (s *source) src() string { - return s.base + path.Join(s.path...) + return path.Join(s.base, s.path) } func (s *source) dst(dst string) string { - return dst + path.Join(s.path...) + return path.Join(dst, s.path) } -func (s *source) append(next ...string) *source { - copyed := make([]string, len(s.path)+len(next)) - copy(copyed, s.path) - copy(copyed[len(s.path):], next) - - return &source{base: s.base, path: copyed} +func (s *source) append(next string) *source { + return &source{base: s.base, path: path.Join(s.path, next)} } type option struct { @@ -79,7 +75,7 @@ type accurateJob struct { func AccurateJob(src string, dsts []string) Option { return func(o *option) *option { - o.accurateJobs = append(o.accurateJobs, &accurateJob{src: src, dsts: dsts}) + o.accurateJobs = append(o.accurateJobs, &accurateJob{src: path.Clean(src), dsts: dsts}) return o } } @@ -144,48 +140,3 @@ func WithEventHandler(h EventHandler) Option { return o } } - -func comparePath(a, b []string) int { - al, bl := len(a), len(b) - - l := al - if bl < al { - l = bl - } - - for idx := 0; idx < l; idx++ { - if a[idx] < b[idx] { - return -1 - } - if a[idx] > b[idx] { - return 1 - } - } - - if al < bl { - return -1 - } - if al > bl { - return 1 - } - return 0 -} - -// isChild return -1(not) 0(equal) 1(child) -func isChild(parent, child []string) int { - pl, cl := len(parent), len(child) - if pl > cl { - return -1 - } - - for idx := 0; idx < pl; idx++ { - if parent[idx] != child[idx] { - return -1 - } - } - - if pl == cl { - return 0 - } - return 1 -} diff --git a/opt_wildcard.go b/opt_wildcard.go index b2781d7..42fea85 100644 --- a/opt_wildcard.go +++ b/opt_wildcard.go @@ -40,7 +40,8 @@ func (job *wildcardJob) check() error { return fmt.Errorf("source path not found") } sort.Slice(job.src, func(i, j int) bool { - return comparePath(job.src[i].path, job.src[j].path) < 0 + si, sj := strings.ReplaceAll(job.src[i].path, "/", "\x00"), strings.ReplaceAll(job.src[j].path, "/", "\x00") + return si < sj }) for _, s := range job.src { src := s.src() @@ -79,16 +80,26 @@ func Source(paths ...string) WildcardJobOption { } base, name := path.Split(p) - j.src = append(j.src, &source{base: base, path: []string{name}}) + j.src = append(j.src, &source{base: base, path: name}) } return j } } +func SourceWithPath(base string, paths ...string) WildcardJobOption { + return func(j *wildcardJob) *wildcardJob { + for _, p := range paths { + j.src = append(j.src, &source{base: base, path: p}) + } + return j + } +} + +// Deprecated: use SourceWithPath instead func AccurateSource(base string, paths ...[]string) WildcardJobOption { return func(j *wildcardJob) *wildcardJob { - for _, path := range paths { - j.src = append(j.src, &source{base: base, path: path}) + for _, p := range paths { + j.src = append(j.src, &source{base: base, path: path.Join(p...)}) } return j } diff --git a/report.go b/report.go index b373fcb..6354493 100644 --- a/report.go +++ b/report.go @@ -2,7 +2,6 @@ package acp import ( "fmt" - "path" "sync" "unsafe" @@ -23,7 +22,7 @@ func NewReportGetter() (EventHandler, ReportGetter) { lock.Lock() defer lock.Unlock() - key := path.Join(e.Job.Path...) + key := e.Job.Path jobs[key] = e.Job case *EventReportError: lock.Lock()