mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
channel: master
version: 1.2.0
source-ref: D:\code\open_source\ant-chrome master
source-commit: f3d7ec5
merged-public-base: 3d264eb
182 lines
3.4 KiB
Go
182 lines
3.4 KiB
Go
package backend
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func backupSyncDir(src, dst string, overwrite bool, stats *backupMergeStats, shouldSkip func(rel string) bool) error {
|
|
if !backupPathExists(src) {
|
|
return nil
|
|
}
|
|
if err := os.MkdirAll(dst, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if d.Type()&os.ModeSymlink != 0 {
|
|
stats.Skipped++
|
|
if d.IsDir() {
|
|
return filepath.SkipDir
|
|
}
|
|
return nil
|
|
}
|
|
rel, err := filepath.Rel(src, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rel == "." {
|
|
return nil
|
|
}
|
|
rel = filepath.ToSlash(rel)
|
|
if shouldSkip != nil && shouldSkip(rel) {
|
|
if d.IsDir() {
|
|
return filepath.SkipDir
|
|
}
|
|
stats.Skipped++
|
|
return nil
|
|
}
|
|
|
|
target := filepath.Join(dst, filepath.FromSlash(rel))
|
|
if d.IsDir() {
|
|
return os.MkdirAll(target, 0755)
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
if overwrite {
|
|
if err := backupCopyFile(path, target); err != nil {
|
|
return err
|
|
}
|
|
stats.Imported++
|
|
return nil
|
|
}
|
|
|
|
if _, err := os.Stat(target); os.IsNotExist(err) {
|
|
if err := backupCopyFile(path, target); err != nil {
|
|
return err
|
|
}
|
|
stats.Imported++
|
|
return nil
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
same, err := backupFilesSame(path, target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if same {
|
|
stats.Skipped++
|
|
} else {
|
|
stats.Conflicts++
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func backupCopyFile(src, dst string) error {
|
|
in, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer in.Close()
|
|
info, err := in.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tmpPath := dst + ".tmp"
|
|
out, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := io.Copy(out, in); err != nil {
|
|
out.Close()
|
|
_ = os.Remove(tmpPath)
|
|
return err
|
|
}
|
|
if err := out.Close(); err != nil {
|
|
_ = os.Remove(tmpPath)
|
|
return err
|
|
}
|
|
if err := os.Rename(tmpPath, dst); err != nil {
|
|
_ = os.Remove(tmpPath)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func backupFilesSame(a, b string) (bool, error) {
|
|
ainfo, err := os.Stat(a)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
binfo, err := os.Stat(b)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if ainfo.Size() != binfo.Size() {
|
|
return false, nil
|
|
}
|
|
ah, err := backupSHA256File(a)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
bh, err := backupSHA256File(b)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return ah == bh, nil
|
|
}
|
|
|
|
func backupSHA256File(path string) (string, error) {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer f.Close()
|
|
h := sha256.New()
|
|
if _, err := io.Copy(h, f); err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(h.Sum(nil)), nil
|
|
}
|
|
|
|
func backupShouldSkipAppDBFile(rel string) bool {
|
|
r := strings.TrimSpace(filepath.ToSlash(rel))
|
|
return r == "app.db" || r == "app.db-wal" || r == "app.db-shm"
|
|
}
|
|
|
|
func backupRemoveContentsExcept(dir string, keep map[string]struct{}) error {
|
|
dir = strings.TrimSpace(dir)
|
|
if dir == "" {
|
|
return nil
|
|
}
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range entries {
|
|
p := filepath.Join(dir, entry.Name())
|
|
if backupPathInSet(p, keep) {
|
|
continue
|
|
}
|
|
if err := os.RemoveAll(p); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|