feat: change path api

This commit is contained in:
Samuel N Cui
2026-03-13 21:14:47 +08:00
parent 8a8f54c525
commit 207085ec89
7 changed files with 37 additions and 78 deletions
+3 -7
View File
@@ -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))
+1 -1
View File
@@ -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
)
+4 -5
View File
@@ -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
}
+7 -4
View File
@@ -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"`
+6 -55
View File
@@ -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
}
+15 -4
View File
@@ -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
}
+1 -2
View File
@@ -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()