From 74f2017e8ccdf2cb15eff80131e4c99cf91c7d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Sun, 29 Dec 2024 02:39:04 +0800 Subject: [PATCH 01/10] :art: Add local file system sync method --- cloud/cloud.go | 10 ++++ cloud/local.go | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 4 files changed, 153 insertions(+) create mode 100644 cloud/local.go diff --git a/cloud/cloud.go b/cloud/cloud.go index 3ee36b3..e8ba892 100644 --- a/cloud/cloud.go +++ b/cloud/cloud.go @@ -39,6 +39,9 @@ type Conf struct { // WebDAV 协议所需配置 WebDAV *ConfWebDAV + // 本地存储服务配置 + Local *ConfLocal + // 以下值非官方存储服务不必传入 Token string // 云端接口鉴权令牌 AvailableSize int64 // 云端存储可用空间字节数 @@ -68,6 +71,13 @@ type ConfWebDAV struct { ConcurrentReqs int // 并发请求数 } +// ConfLocal 用于描述本地存储服务配置信息。 +type ConfLocal struct { + Endpoint string // 服务端点 (本地文件系统目录) + Timeout int // 超时时间,单位:秒 + ConcurrentReqs int // 并发请求数 +} + // Cloud 描述了云端存储服务,接入云端存储服务时需要实现该接口。 type Cloud interface { diff --git a/cloud/local.go b/cloud/local.go new file mode 100644 index 0000000..bead976 --- /dev/null +++ b/cloud/local.go @@ -0,0 +1,140 @@ +// DejaVu - Data snapshot and sync. +// Copyright (c) 2022-present, b3log.org +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package cloud + +import ( + "sync" + + "github.com/ricochet2200/go-disk-usage/du" + "github.com/siyuan-note/dejavu/entity" +) + +// Local 描述了本地文件系统服务实现。 +type Local struct { + *BaseCloud + + lock sync.Mutex +} + +func NewLocal(baseCloud *BaseCloud) (ret *Local) { + ret = &Local{ + BaseCloud: baseCloud, + lock: sync.Mutex{}, + } + return +} + +func (local *Local) CreateRepo(name string) (err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) RemoveRepo(name string) (err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetRepos() (repos []*Repo, size int64, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) UploadObject(filePath string, overwrite bool) (err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) DownloadObject(filePath string) (data []byte, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) RemoveObject(key string) (err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetTags() (tags []*Ref, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetIndexes(page int) (indexes []*entity.Index, pageCount, totalCount int, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetRefsFiles() (fileIDs []string, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetChunks(checkChunkIDs []string) (chunkIDs []string, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetStat() (stat *Stat, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) ListObjects(pathPrefix string) (objInfos map[string]*entity.ObjectInfo, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetIndex(id string) (index *entity.Index, err error) { + // TODO + err = ErrUnsupported + return +} + +func (local *Local) GetConcurrentReqs() int { + return local.Local.ConcurrentReqs +} + +func (local *Local) GetConf() *Conf { + return local.Conf +} + +func (local *Local) GetAvailableSize() int64 { + info := du.NewDiskUsage(local.Local.Endpoint) + return int64(info.Free()) +} + +func (local *Local) AddTraffic(*Traffic) { + return +} diff --git a/go.mod b/go.mod index beb2b2e..6daacba 100644 --- a/go.mod +++ b/go.mod @@ -56,6 +56,7 @@ require ( github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/quic-go v0.48.2 // indirect github.com/refraction-networking/utls v1.6.7 // indirect + github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.uber.org/mock v0.5.0 // indirect diff --git a/go.sum b/go.sum index b63bbfe..e118c98 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/restic/chunker v0.4.0 h1:YUPYCUn70MYP7VO4yllypp2SjmsRhRJaad3xKu1QFRw= github.com/restic/chunker v0.4.0/go.mod h1:z0cH2BejpW636LXw0R/BGyv+Ey8+m9QGiOanDHItzyw= +github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 h1:d54EL9l+XteliUfUCGsEwwuk65dmmxX85VXF+9T6+50= +github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285/go.mod h1:fxIDly1xtudczrZeOOlfaUvd2OPb2qZAPuWdU2BsBTk= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= From f4d944544e72ea12e8b300170c031034b795381f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Sun, 29 Dec 2024 19:22:23 +0800 Subject: [PATCH 02/10] :art: Implement repo-related methods --- cloud/local.go | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/cloud/local.go b/cloud/local.go index bead976..4c39b97 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -17,6 +17,9 @@ package cloud import ( + "os" + "path" + "sort" "sync" "github.com/ricochet2200/go-disk-usage/du" @@ -39,20 +42,26 @@ func NewLocal(baseCloud *BaseCloud) (ret *Local) { } func (local *Local) CreateRepo(name string) (err error) { - // TODO - err = ErrUnsupported + repoPath := path.Join(local.Local.Endpoint, name) + err = os.MkdirAll(repoPath, 0755) return } func (local *Local) RemoveRepo(name string) (err error) { - // TODO - err = ErrUnsupported + repoPath := path.Join(local.Local.Endpoint, name) + err = os.RemoveAll(repoPath) return } func (local *Local) GetRepos() (repos []*Repo, size int64, err error) { - // TODO - err = ErrUnsupported + repos, err = local.listRepos() + if nil != err { + return + } + + for _, repo := range repos { + size += repo.Size + } return } @@ -138,3 +147,28 @@ func (local *Local) GetAvailableSize() int64 { func (local *Local) AddTraffic(*Traffic) { return } + +func (local *Local) listRepos() (ret []*Repo, err error) { + entries, err := os.ReadDir(local.Local.Endpoint) + if err != nil { + return + } + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + entryInfo, err := entry.Info() + if nil != err { + continue + } + ret = append(ret, &Repo{ + Name: entry.Name(), + Size: entryInfo.Size(), + Updated: entryInfo.ModTime().Local().Format("2006-01-02 15:04:05"), + }) + } + sort.Slice(ret, func(i, j int) bool { return ret[i].Name < ret[j].Name }) + return +} From 865cd4377f0a686218ce93076350e370c30e4313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:25:11 +0800 Subject: [PATCH 03/10] :art: Implement object-related methods --- cloud/cloud.go | 6 +-- cloud/local.go | 120 +++++++++++++++++++++++++++++++++++++++++------- cloud/webdav.go | 17 +------ 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/cloud/cloud.go b/cloud/cloud.go index e8ba892..8e1a2dc 100644 --- a/cloud/cloud.go +++ b/cloud/cloud.go @@ -215,12 +215,12 @@ func (baseCloud *BaseCloud) GetRepos() (repos []*Repo, size int64, err error) { return } -func (baseCloud *BaseCloud) UploadObject(filePath string, overwrite bool) (err error) { +func (baseCloud *BaseCloud) UploadObject(filePath string, overwrite bool) (length int64, err error) { err = ErrUnsupported return } -func (baseCloud *BaseCloud) UploadBytes(filePath string, data []byte, overwrite bool) (err error) { +func (baseCloud *BaseCloud) UploadBytes(filePath string, data []byte, overwrite bool) (length int64, err error) { err = ErrUnsupported return } @@ -230,7 +230,7 @@ func (baseCloud *BaseCloud) DownloadObject(filePath string) (data []byte, err er return } -func (baseCloud *BaseCloud) RemoveObject(key string) (err error) { +func (baseCloud *BaseCloud) RemoveObject(filePath string) (err error) { err = ErrUnsupported return } diff --git a/cloud/local.go b/cloud/local.go index 4c39b97..be3bdb3 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -19,11 +19,14 @@ package cloud import ( "os" "path" + "path/filepath" "sort" + "strings" "sync" "github.com/ricochet2200/go-disk-usage/du" "github.com/siyuan-note/dejavu/entity" + "github.com/siyuan-note/logging" ) // Local 描述了本地文件系统服务实现。 @@ -65,27 +68,110 @@ func (local *Local) GetRepos() (repos []*Repo, size int64, err error) { return } -func (local *Local) UploadObject(filePath string, overwrite bool) (err error) { - // TODO - err = ErrUnsupported +func (local *Local) UploadObject(filePath string, overwrite bool) (length int64, err error) { + absFilePath := filepath.Join(local.Conf.RepoPath, filePath) + data, err := os.ReadFile(absFilePath) + if nil != err { + return + } + + length, err = local.UploadBytes(filePath, data, overwrite) return } -func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (err error) { - // TODO - err = ErrUnsupported +func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (length int64, err error) { + length = int64(len(data)) + + key := local.getCurrentRepoObjectFilePath(filePath) + + folder := path.Dir(key) + err = os.MkdirAll(folder, 0755) + if nil != err { + return + } + + if !overwrite { // not overwrite the file + _, err = os.Stat(key) + if err != nil { + if os.IsNotExist(err) { // file not exist + // do nothing and continue + err = nil + } else { // other error + logging.LogErrorf("upload object [%s] failed: %s", key, err) + return + } + } + } + + err = os.WriteFile(key, data, 0644) + if nil != err { + logging.LogErrorf("upload object [%s] failed: %s", key, err) + return + } + + //logging.LogInfof("uploaded object [%s]", key) return } func (local *Local) DownloadObject(filePath string) (data []byte, err error) { - // TODO - err = ErrUnsupported + key := local.getCurrentRepoObjectFilePath(filePath) + + data, err = os.ReadFile(key) + if nil != err { + return + } + + //logging.LogInfof("downloaded object [%s]", key) return } -func (local *Local) RemoveObject(key string) (err error) { - // TODO - err = ErrUnsupported +func (local *Local) RemoveObject(filePath string) (err error) { + key := local.getCurrentRepoObjectFilePath(filePath) + + err = os.Remove(key) + if err != nil { + if os.IsNotExist(err) { + err = nil + } else { + logging.LogErrorf("remove object [%s] failed: %s", key, err) + } + return + } + + //logging.LogInfof("removed object [%s]", key) + return +} + +func (local *Local) ListObjects(pathPrefix string) (ret map[string]*entity.ObjectInfo, err error) { + ret = map[string]*entity.ObjectInfo{} + + endWithSlash := strings.HasSuffix(pathPrefix, "/") + pathPrefix = local.getCurrentRepoObjectFilePath(pathPrefix) + if endWithSlash { + pathPrefix += "/" + } + + entries, err := os.ReadDir(pathPrefix) + if err != nil { + logging.LogErrorf("list objects [%s] failed: %s", pathPrefix, err) + return + } + + for _, entry := range entries { + entryInfo, err := entry.Info() + if nil != err { + logging.LogErrorf("get object [%s] info failed: %s", path.Join(pathPrefix, entry.Name()), err) + continue + } + + filePath := entry.Name() + ret[filePath] = &entity.ObjectInfo{ + Path: filePath, + Size: entryInfo.Size(), + } + } + + //logging.LogInfof("list objects [%s]", pathPrefix) return } @@ -119,12 +205,6 @@ func (local *Local) GetStat() (stat *Stat, err error) { return } -func (local *Local) ListObjects(pathPrefix string) (objInfos map[string]*entity.ObjectInfo, err error) { - // TODO - err = ErrUnsupported - return -} - func (local *Local) GetIndex(id string) (index *entity.Index, err error) { // TODO err = ErrUnsupported @@ -151,6 +231,7 @@ func (local *Local) AddTraffic(*Traffic) { func (local *Local) listRepos() (ret []*Repo, err error) { entries, err := os.ReadDir(local.Local.Endpoint) if err != nil { + logging.LogErrorf("list repos [%s] failed: %s", local.Local.Endpoint, err) return } @@ -161,6 +242,7 @@ func (local *Local) listRepos() (ret []*Repo, err error) { entryInfo, err := entry.Info() if nil != err { + logging.LogErrorf("get repo [%s] info failed: %s", path.Join(local.Local.Endpoint, entry.Name()), err) continue } ret = append(ret, &Repo{ @@ -172,3 +254,7 @@ func (local *Local) listRepos() (ret []*Repo, err error) { sort.Slice(ret, func(i, j int) bool { return ret[i].Name < ret[j].Name }) return } + +func (local *Local) getCurrentRepoObjectFilePath(filePath string) string { + return path.Join(local.Local.Endpoint, local.Dir, "repo", filePath) +} diff --git a/cloud/webdav.go b/cloud/webdav.go index f155cb6..74314bd 100644 --- a/cloud/webdav.go +++ b/cloud/webdav.go @@ -69,20 +69,7 @@ func (webdav *WebDAV) UploadObject(filePath string, overwrite bool) (length int6 return } - key := path.Join(webdav.Dir, "siyuan", "repo", filePath) - folder := path.Dir(key) - err = webdav.mkdirAll(folder) - if nil != err { - return - } - - err = webdav.Client.Write(key, data, 0644) - err = webdav.parseErr(err) - if nil != err { - logging.LogErrorf("upload object [%s] failed: %s", key, err) - return - } - //logging.LogInfof("uploaded object [%s]", key) + length, err = webdav.UploadBytes(filePath, data, overwrite) return } @@ -271,7 +258,7 @@ func (webdav *WebDAV) ListObjects(pathPrefix string) (ret map[string]*entity.Obj infos, err := webdav.Client.ReadDir(pathPrefix) if nil != err { - logging.LogErrorf("list objects failed: %s", err) + logging.LogErrorf("list objects [%s] failed: %s", pathPrefix, err) return } From ffaaa7f4374a915ca4ad20d28466f5d330e8ff20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:38:45 +0800 Subject: [PATCH 04/10] :art: Implement index-related methods --- cloud/cloud.go | 2 +- cloud/local.go | 248 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 208 insertions(+), 42 deletions(-) diff --git a/cloud/cloud.go b/cloud/cloud.go index 8e1a2dc..3cebef4 100644 --- a/cloud/cloud.go +++ b/cloud/cloud.go @@ -245,7 +245,7 @@ func (baseCloud *BaseCloud) GetIndexes(page int) (indexes []*entity.Index, pageC return } -func (baseCloud *BaseCloud) GetRefsFiles() (fileIDs []string, err error) { +func (baseCloud *BaseCloud) GetRefsFiles() (fileIDs []string, refs []*Ref, err error) { err = ErrUnsupported return } diff --git a/cloud/local.go b/cloud/local.go index be3bdb3..025498d 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -17,6 +17,7 @@ package cloud import ( + "math" "os" "path" "path/filepath" @@ -24,6 +25,7 @@ import ( "strings" "sync" + "github.com/88250/gulu" "github.com/ricochet2200/go-disk-usage/du" "github.com/siyuan-note/dejavu/entity" "github.com/siyuan-note/logging" @@ -36,8 +38,8 @@ type Local struct { lock sync.Mutex } -func NewLocal(baseCloud *BaseCloud) (ret *Local) { - ret = &Local{ +func NewLocal(baseCloud *BaseCloud) (local *Local) { + local = &Local{ BaseCloud: baseCloud, lock: sync.Mutex{}, } @@ -58,7 +60,7 @@ func (local *Local) RemoveRepo(name string) (err error) { func (local *Local) GetRepos() (repos []*Repo, size int64, err error) { repos, err = local.listRepos() - if nil != err { + if err != nil { return } @@ -71,7 +73,7 @@ func (local *Local) GetRepos() (repos []*Repo, size int64, err error) { func (local *Local) UploadObject(filePath string, overwrite bool) (length int64, err error) { absFilePath := filepath.Join(local.Conf.RepoPath, filePath) data, err := os.ReadFile(absFilePath) - if nil != err { + if err != nil { return } @@ -82,11 +84,11 @@ func (local *Local) UploadObject(filePath string, overwrite bool) (length int64, func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (length int64, err error) { length = int64(len(data)) - key := local.getCurrentRepoObjectFilePath(filePath) + key := path.Join(local.getCurrentRepoDirPath(), filePath) folder := path.Dir(key) err = os.MkdirAll(folder, 0755) - if nil != err { + if err != nil { return } @@ -104,7 +106,7 @@ func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (l } err = os.WriteFile(key, data, 0644) - if nil != err { + if err != nil { logging.LogErrorf("upload object [%s] failed: %s", key, err) return } @@ -114,10 +116,10 @@ func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (l } func (local *Local) DownloadObject(filePath string) (data []byte, err error) { - key := local.getCurrentRepoObjectFilePath(filePath) + key := path.Join(local.getCurrentRepoDirPath(), filePath) data, err = os.ReadFile(key) - if nil != err { + if err != nil { return } @@ -126,7 +128,7 @@ func (local *Local) DownloadObject(filePath string) (data []byte, err error) { } func (local *Local) RemoveObject(filePath string) (err error) { - key := local.getCurrentRepoObjectFilePath(filePath) + key := path.Join(local.getCurrentRepoDirPath(), filePath) err = os.Remove(key) if err != nil { @@ -142,11 +144,11 @@ func (local *Local) RemoveObject(filePath string) (err error) { return } -func (local *Local) ListObjects(pathPrefix string) (ret map[string]*entity.ObjectInfo, err error) { - ret = map[string]*entity.ObjectInfo{} +func (local *Local) ListObjects(pathPrefix string) (objects map[string]*entity.ObjectInfo, err error) { + objects = map[string]*entity.ObjectInfo{} endWithSlash := strings.HasSuffix(pathPrefix, "/") - pathPrefix = local.getCurrentRepoObjectFilePath(pathPrefix) + pathPrefix = path.Join(local.getCurrentRepoDirPath(), pathPrefix) if endWithSlash { pathPrefix += "/" } @@ -158,14 +160,15 @@ func (local *Local) ListObjects(pathPrefix string) (ret map[string]*entity.Objec } for _, entry := range entries { - entryInfo, err := entry.Info() - if nil != err { + entryInfo, infoErr := entry.Info() + if infoErr != nil { + err = infoErr logging.LogErrorf("get object [%s] info failed: %s", path.Join(pathPrefix, entry.Name()), err) - continue + return } filePath := entry.Name() - ret[filePath] = &entity.ObjectInfo{ + objects[filePath] = &entity.ObjectInfo{ Path: filePath, Size: entryInfo.Size(), } @@ -176,38 +179,119 @@ func (local *Local) ListObjects(pathPrefix string) (ret map[string]*entity.Objec } func (local *Local) GetTags() (tags []*Ref, err error) { - // TODO - err = ErrUnsupported + tags, err = local.listRepoRefs("tags") + if err != nil { + return + } + if 1 > len(tags) { + tags = []*Ref{} + } return } func (local *Local) GetIndexes(page int) (indexes []*entity.Index, pageCount, totalCount int, err error) { - // TODO - err = ErrUnsupported + data, err := local.DownloadObject("indexes-v2.json") + if err != nil { + if os.IsNotExist(err) { + err = nil + } + return + } + + data, err = compressDecoder.DecodeAll(data, nil) + if err != nil { + return + } + + indexesJSON := &Indexes{} + if err = gulu.JSON.UnmarshalJSON(data, indexesJSON); err != nil { + return + } + + totalCount = len(indexesJSON.Indexes) + pageCount = int(math.Ceil(float64(totalCount) / float64(pageSize))) + + start := (page - 1) * pageSize + end := page * pageSize + if end > totalCount { + end = totalCount + } + + for i := start; i < end; i++ { + index, getErr := local.repoIndex(indexesJSON.Indexes[i].ID) + if getErr != nil { + logging.LogWarnf("get repo index [%s] failed: %s", indexesJSON.Indexes[i], getErr) + continue + } + + index.Files = nil // Optimize the performance of obtaining cloud snapshots https://github.com/siyuan-note/siyuan/issues/8387 + indexes = append(indexes, index) + } return } -func (local *Local) GetRefsFiles() (fileIDs []string, err error) { - // TODO - err = ErrUnsupported +func (local *Local) GetRefsFiles() (fileIDs []string, refs []*Ref, err error) { + refs, err = local.listRepoRefs("") + var files []string + for _, ref := range refs { + index, getErr := local.repoIndex(ref.ID) + if getErr != nil { + return + } + if index == nil { + continue + } + + files = append(files, index.Files...) + } + + fileIDs = gulu.Str.RemoveDuplicatedElem(files) + if 1 > len(fileIDs) { + fileIDs = []string{} + } return } func (local *Local) GetChunks(checkChunkIDs []string) (chunkIDs []string, err error) { - // TODO - err = ErrUnsupported - return -} + repoObjectsPath := path.Join(local.getCurrentRepoDirPath(), "objects") + var keys []string + for _, chunkID := range checkChunkIDs { + key := path.Join(repoObjectsPath, chunkID[:2], chunkID[2:]) + keys = append(keys, key) + } -func (local *Local) GetStat() (stat *Stat, err error) { - // TODO - err = ErrUnsupported + notFound, err := local.getNotFound(keys) + if err != nil { + return + } + + var notFoundChunkIDs []string + for _, key := range notFound { + chunkID := strings.TrimPrefix(key, repoObjectsPath) + chunkID = strings.ReplaceAll(chunkID, "/", "") + notFoundChunkIDs = append(notFoundChunkIDs, chunkID) + } + + chunkIDs = append(chunkIDs, notFoundChunkIDs...) + chunkIDs = gulu.Str.RemoveDuplicatedElem(chunkIDs) + if 1 > len(chunkIDs) { + chunkIDs = []string{} + } return } +// func (local *Local) GetStat() (stat *Stat, err error) + func (local *Local) GetIndex(id string) (index *entity.Index, err error) { - // TODO - err = ErrUnsupported + index, err = local.repoIndex(id) + if err != nil { + logging.LogErrorf("get repo index [%s] failed: %s", id, err) + return + } + if index == nil { + err = ErrCloudObjectNotFound + return + } return } @@ -228,7 +312,7 @@ func (local *Local) AddTraffic(*Traffic) { return } -func (local *Local) listRepos() (ret []*Repo, err error) { +func (local *Local) listRepos() (repos []*Repo, err error) { entries, err := os.ReadDir(local.Local.Endpoint) if err != nil { logging.LogErrorf("list repos [%s] failed: %s", local.Local.Endpoint, err) @@ -240,21 +324,103 @@ func (local *Local) listRepos() (ret []*Repo, err error) { continue } - entryInfo, err := entry.Info() - if nil != err { + entryInfo, infoErr := entry.Info() + if infoErr != nil { + err = infoErr logging.LogErrorf("get repo [%s] info failed: %s", path.Join(local.Local.Endpoint, entry.Name()), err) - continue + return } - ret = append(ret, &Repo{ + repos = append(repos, &Repo{ Name: entry.Name(), Size: entryInfo.Size(), Updated: entryInfo.ModTime().Local().Format("2006-01-02 15:04:05"), }) } - sort.Slice(ret, func(i, j int) bool { return ret[i].Name < ret[j].Name }) + sort.Slice(repos, func(i, j int) bool { return repos[i].Name < repos[j].Name }) + return +} + +func (local *Local) listRepoRefs(refPrefix string) (refs []*Ref, err error) { + keyPath := path.Join(local.getCurrentRepoDirPath(), "refs", refPrefix) + entries, err := os.ReadDir(keyPath) + if err != nil { + logging.LogErrorf("list repo refs [%s] failed: %s", keyPath, err) + return + } + + for _, entry := range entries { + if entry.IsDir() { + continue + } + + entryInfo, infoErr := entry.Info() + if infoErr != nil { + err = infoErr + logging.LogErrorf("get repo ref [%s] info failed: %s", path.Join(local.Local.Endpoint, entry.Name()), err) + return + } + + data, readErr := os.ReadFile(path.Join(keyPath, entry.Name())) + if readErr != nil { + err = readErr + logging.LogErrorf("get repo ref [%s] ID failed: %s", path.Join(local.Local.Endpoint, entry.Name()), err) + return + } + + id := string(data) + ref := &Ref{ + Name: entry.Name(), + ID: id, + Updated: entryInfo.ModTime().Local().Format("2006-01-02 15:04:05"), + } + refs = append(refs, ref) + } + return +} + +func (local *Local) repoIndex(id string) (index *entity.Index, err error) { + indexFilePath := path.Join(local.getCurrentRepoDirPath(), "indexes", id) + + indexFileInfo, err := os.Stat(indexFilePath) + if err != nil { + return + } + if 1 > indexFileInfo.Size() { + return + } + + data, err := os.ReadFile(indexFilePath) + if err != nil { + return + } + + data, err = compressDecoder.DecodeAll(data, nil) + if err != nil { + return + } + + index = &entity.Index{} + err = gulu.JSON.UnmarshalJSON(data, index) + if err != nil { + return + } + + return +} + +func (local *Local) getNotFound(keys []string) (ret []string, err error) { + if 1 > len(keys) { + return + } + for _, key := range keys { + _, statErr := os.Stat(key) + if os.IsNotExist(statErr) { + ret = append(ret, key) + } + } return } -func (local *Local) getCurrentRepoObjectFilePath(filePath string) string { - return path.Join(local.Local.Endpoint, local.Dir, "repo", filePath) +func (local *Local) getCurrentRepoDirPath() string { + return path.Join(local.Local.Endpoint, local.Dir) } From fc1b38b824f84c312ec2209e6c6e98ae1e5aae99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 01:07:14 +0800 Subject: [PATCH 05/10] :art: Adjust concurrent request count --- cloud/local.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cloud/local.go b/cloud/local.go index 025498d..6c22f1b 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -147,11 +147,7 @@ func (local *Local) RemoveObject(filePath string) (err error) { func (local *Local) ListObjects(pathPrefix string) (objects map[string]*entity.ObjectInfo, err error) { objects = map[string]*entity.ObjectInfo{} - endWithSlash := strings.HasSuffix(pathPrefix, "/") pathPrefix = path.Join(local.getCurrentRepoDirPath(), pathPrefix) - if endWithSlash { - pathPrefix += "/" - } entries, err := os.ReadDir(pathPrefix) if err != nil { @@ -295,8 +291,15 @@ func (local *Local) GetIndex(id string) (index *entity.Index, err error) { return } -func (local *Local) GetConcurrentReqs() int { - return local.Local.ConcurrentReqs +func (local *Local) GetConcurrentReqs() (ret int) { + ret = local.Local.ConcurrentReqs + if ret < 1 { + ret = 16 + } + if ret > 256 { + ret = 256 + } + return } func (local *Local) GetConf() *Conf { From 65df2151cb7206e09f55e6340838329e66d80886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 02:13:59 +0800 Subject: [PATCH 06/10] :bug: Fix error format --- cloud/local.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cloud/local.go b/cloud/local.go index 6c22f1b..2d4a0b2 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -120,6 +120,9 @@ func (local *Local) DownloadObject(filePath string) (data []byte, err error) { data, err = os.ReadFile(key) if err != nil { + if os.IsNotExist(err) { + err = ErrCloudObjectNotFound + } return } @@ -296,8 +299,8 @@ func (local *Local) GetConcurrentReqs() (ret int) { if ret < 1 { ret = 16 } - if ret > 256 { - ret = 256 + if ret > 1024 { + ret = 1024 } return } From 1bcc6974d5a96df8bd240d94d160d999ed1e56f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:31:36 +0800 Subject: [PATCH 07/10] :bug: Fix invalid error return --- cloud/s3.go | 1 + cloud/webdav.go | 1 + 2 files changed, 2 insertions(+) diff --git a/cloud/s3.go b/cloud/s3.go index 5bf45fd..7f3dc4f 100644 --- a/cloud/s3.go +++ b/cloud/s3.go @@ -230,6 +230,7 @@ func (s3 *S3) GetRefsFiles() (fileIDs []string, refs []*Ref, err error) { for _, ref := range refs { index, getErr := s3.repoIndex(ref.ID) if nil != getErr { + err = getErr return } if nil == index { diff --git a/cloud/webdav.go b/cloud/webdav.go index 74314bd..3d08b8a 100644 --- a/cloud/webdav.go +++ b/cloud/webdav.go @@ -179,6 +179,7 @@ func (webdav *WebDAV) GetRefsFiles() (fileIDs []string, refs []*Ref, err error) for _, ref := range refs { index, getErr := webdav.repoIndex(repoKey, ref.ID) if nil != getErr { + err = getErr return } if nil == index { From 8a67255493276fab3cce8fcf7af0f8ee546f50e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:48:14 +0800 Subject: [PATCH 08/10] :art: Resolve review conversation --- cloud/local.go | 23 +++++++++-------------- go.mod | 7 +++++-- go.sum | 13 ++++++++++--- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cloud/local.go b/cloud/local.go index 2d4a0b2..82a34c3 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -23,10 +23,9 @@ import ( "path/filepath" "sort" "strings" - "sync" "github.com/88250/gulu" - "github.com/ricochet2200/go-disk-usage/du" + "github.com/shirou/gopsutil/v3/disk" "github.com/siyuan-note/dejavu/entity" "github.com/siyuan-note/logging" ) @@ -34,14 +33,11 @@ import ( // Local 描述了本地文件系统服务实现。 type Local struct { *BaseCloud - - lock sync.Mutex } func NewLocal(baseCloud *BaseCloud) (local *Local) { local = &Local{ BaseCloud: baseCloud, - lock: sync.Mutex{}, } return } @@ -82,10 +78,7 @@ func (local *Local) UploadObject(filePath string, overwrite bool) (length int64, } func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (length int64, err error) { - length = int64(len(data)) - key := path.Join(local.getCurrentRepoDirPath(), filePath) - folder := path.Dir(key) err = os.MkdirAll(folder, 0755) if err != nil { @@ -111,6 +104,8 @@ func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (l return } + length = int64(len(data)) + //logging.LogInfof("uploaded object [%s]", key) return } @@ -132,7 +127,6 @@ func (local *Local) DownloadObject(filePath string) (data []byte, err error) { func (local *Local) RemoveObject(filePath string) (err error) { key := path.Join(local.getCurrentRepoDirPath(), filePath) - err = os.Remove(key) if err != nil { if os.IsNotExist(err) { @@ -149,9 +143,7 @@ func (local *Local) RemoveObject(filePath string) (err error) { func (local *Local) ListObjects(pathPrefix string) (objects map[string]*entity.ObjectInfo, err error) { objects = map[string]*entity.ObjectInfo{} - pathPrefix = path.Join(local.getCurrentRepoDirPath(), pathPrefix) - entries, err := os.ReadDir(pathPrefix) if err != nil { logging.LogErrorf("list objects [%s] failed: %s", pathPrefix, err) @@ -209,7 +201,6 @@ func (local *Local) GetIndexes(page int) (indexes []*entity.Index, pageCount, to totalCount = len(indexesJSON.Indexes) pageCount = int(math.Ceil(float64(totalCount) / float64(pageSize))) - start := (page - 1) * pageSize end := page * pageSize if end > totalCount { @@ -310,8 +301,12 @@ func (local *Local) GetConf() *Conf { } func (local *Local) GetAvailableSize() int64 { - info := du.NewDiskUsage(local.Local.Endpoint) - return int64(info.Free()) + usage, err := disk.Usage(local.Local.Endpoint) + if err != nil { + return math.MaxInt64 + } + + return int64(usage.Free) } func (local *Local) AddTraffic(*Traffic) { diff --git a/go.mod b/go.mod index 6daacba..6320d99 100644 --- a/go.mod +++ b/go.mod @@ -18,12 +18,14 @@ require ( github.com/qiniu/go-sdk/v7 v7.20.2 github.com/restic/chunker v0.4.0 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 + github.com/shirou/gopsutil/v3 v3.24.5 github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4 github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 github.com/siyuan-note/filelock v0.0.0-20241212013445-c66518cdacfa github.com/siyuan-note/httpclient v0.0.0-20241220030420-75c76bea8a71 github.com/siyuan-note/logging v0.0.0-20241218085028-6514639a9742 github.com/studio-b12/gowebdav v0.9.0 + github.com/vmihailenco/msgpack/v5 v5.3.5 ) require ( @@ -45,6 +47,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect @@ -53,12 +56,12 @@ require ( github.com/imroc/req/v3 v3.49.0 // indirect github.com/onsi/ginkgo/v2 v2.22.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/quic-go v0.48.2 // indirect github.com/refraction-networking/utls v1.6.7 // indirect - github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect diff --git a/go.sum b/go.sum index e118c98..3054b77 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= @@ -102,6 +104,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk= github.com/qiniu/go-sdk/v7 v7.20.2 h1:Jd+ZJs79APo0dnRlv3aA/uEP7b44flP+p32Lek/WxlY= github.com/qiniu/go-sdk/v7 v7.20.2/go.mod h1:ZnEP1rOOi7weF+yzM2qZMHI0z1ht+KjVuNAuKTQW3aM= @@ -114,12 +118,12 @@ github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/restic/chunker v0.4.0 h1:YUPYCUn70MYP7VO4yllypp2SjmsRhRJaad3xKu1QFRw= github.com/restic/chunker v0.4.0/go.mod h1:z0cH2BejpW636LXw0R/BGyv+Ey8+m9QGiOanDHItzyw= -github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 h1:d54EL9l+XteliUfUCGsEwwuk65dmmxX85VXF+9T6+50= -github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285/go.mod h1:fxIDly1xtudczrZeOOlfaUvd2OPb2qZAPuWdU2BsBTk= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4 h1:kJaw5L/evyW6LcB9IQT8PR4ppx8JVqOFP9Ix3rfwSrc= github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4/go.mod h1:UYcCCY+0wh+GmUoDOaO63j1sV5lgy7laLAk1XhEiUis= github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 h1:lM5v8BfNtbOL5jYwhCdMYBcYtr06IYBKjjSLAPMKTM8= @@ -141,7 +145,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/studio-b12/gowebdav v0.9.0 h1:1j1sc9gQnNxbXXM4M/CebPOX4aXYtr7MojAVcN4dHjU= github.com/studio-b12/gowebdav v0.9.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= -github.com/vmihailenco/msgpack v4.0.4/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -149,6 +152,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -179,7 +184,9 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 29fcc8ca7870208f5ad5936444d177eb34c2b781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:01:15 +0800 Subject: [PATCH 09/10] :art: Resolve review conversation --- cloud/cloud.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cloud/cloud.go b/cloud/cloud.go index 3cebef4..781428b 100644 --- a/cloud/cloud.go +++ b/cloud/cloud.go @@ -73,9 +73,13 @@ type ConfWebDAV struct { // ConfLocal 用于描述本地存储服务配置信息。 type ConfLocal struct { - Endpoint string // 服务端点 (本地文件系统目录) - Timeout int // 超时时间,单位:秒 - ConcurrentReqs int // 并发请求数 + // 服务端点 (本地文件系统目录) + // + // "D:/path/to/repos/directory" // Windows + // "/path/to/repos/directory" // Unix + Endpoint string + Timeout int // 超时时间,单位:秒 + ConcurrentReqs int // 并发请求数 } // Cloud 描述了云端存储服务,接入云端存储服务时需要实现该接口。 From 67d893524ed5d666367ed3bf93ebaef521a3990c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:02:15 +0800 Subject: [PATCH 10/10] :art: Resolve review conversation --- cloud/local.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cloud/local.go b/cloud/local.go index 82a34c3..907736b 100644 --- a/cloud/local.go +++ b/cloud/local.go @@ -112,7 +112,6 @@ func (local *Local) UploadBytes(filePath string, data []byte, overwrite bool) (l func (local *Local) DownloadObject(filePath string) (data []byte, err error) { key := path.Join(local.getCurrentRepoDirPath(), filePath) - data, err = os.ReadFile(key) if err != nil { if os.IsNotExist(err) {