mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-02 04:16:38 +08:00
split organize pipeline helpers
This commit is contained in:
@@ -205,169 +205,9 @@ func (p *OrganizePipelineService) shouldScan(req OrganizePipelineRequest, res *O
|
|||||||
return OrganizeResultNeedsVisibilitySync(res)
|
return OrganizeResultNeedsVisibilitySync(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func organizeScanRoot(res *OrganizeResult, path string) string {
|
|
||||||
if res == nil {
|
|
||||||
if strings.TrimSpace(path) == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return filepath.Dir(path)
|
|
||||||
}
|
|
||||||
var root string
|
|
||||||
for _, item := range res.Items {
|
|
||||||
if !organizeItemNeedsVisibilitySync(item) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
target := strings.TrimSpace(item.Target)
|
|
||||||
if target == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dir := filepath.Dir(target)
|
|
||||||
if root == "" {
|
|
||||||
root = dir
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
root = commonPathRoot(root, dir)
|
|
||||||
}
|
|
||||||
if root != "" {
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(path) != "" {
|
|
||||||
return filepath.Dir(path)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(res.DestPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func organizeItemNeedsVisibilitySync(item OrganizePreviewItem) bool {
|
|
||||||
switch item.Action {
|
|
||||||
case "organize", "replace", "reclassify", "cleanup":
|
|
||||||
return true
|
|
||||||
case "skip":
|
|
||||||
switch item.Reason {
|
|
||||||
case organizeSkipAlreadyOrganized, organizeSkipTargetExists, "duplicate exists", "target exists":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func commonPathRoot(a, b string) string {
|
|
||||||
a = filepath.Clean(strings.TrimSpace(a))
|
|
||||||
b = filepath.Clean(strings.TrimSpace(b))
|
|
||||||
if a == "" || a == "." {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
if b == "" || b == "." {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
if pathWithin(a, b) {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
if pathWithin(b, a) {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
parent := filepath.Dir(a)
|
|
||||||
if parent == a || parent == "." {
|
|
||||||
return parent
|
|
||||||
}
|
|
||||||
if pathWithin(b, parent) {
|
|
||||||
return parent
|
|
||||||
}
|
|
||||||
a = parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) scrapeAfter(ctx context.Context, req OrganizePipelineRequest) bool {
|
func (p *OrganizePipelineService) scrapeAfter(ctx context.Context, req OrganizePipelineRequest) bool {
|
||||||
if req.ScrapeAfter != nil {
|
if req.ScrapeAfter != nil {
|
||||||
return *req.ScrapeAfter
|
return *req.ScrapeAfter
|
||||||
}
|
}
|
||||||
return OrganizeScrapeAfterEnabled(ctx, p.repo)
|
return OrganizeScrapeAfterEnabled(ctx, p.repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *OrganizePipelineService) startTask(ctx context.Context, req OrganizePipelineRequest, opts OrganizeOptions) *TaskHandle {
|
|
||||||
if p == nil || p.tasks == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
name := strings.TrimSpace(req.TaskName)
|
|
||||||
if name == "" {
|
|
||||||
name = p.defaultTaskName(req)
|
|
||||||
}
|
|
||||||
message := "正在整理/重命名/入库"
|
|
||||||
if req.DryRun {
|
|
||||||
message = "正在预览整理/重命名"
|
|
||||||
}
|
|
||||||
return p.tasks.Start(TaskKindOrganize, name, TaskUpdate{
|
|
||||||
Stage: "organize",
|
|
||||||
SourcePath: firstNonEmpty(opts.SourcePath, p.defaultSourcePath(ctx, req)),
|
|
||||||
DestPath: firstNonEmpty(opts.DestPath, p.defaultDestPath(ctx, req)),
|
|
||||||
Message: message,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) finishTask(task *TaskHandle, err error, stage, message string, res *OrganizeResult) {
|
|
||||||
if task == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
task.Finish(err, TaskUpdate{
|
|
||||||
Stage: stage,
|
|
||||||
Message: message,
|
|
||||||
Metrics: OrganizeTaskMetrics(res),
|
|
||||||
Details: OrganizeTaskDetails(res, 8),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) defaultTaskName(req OrganizePipelineRequest) string {
|
|
||||||
switch req.Trigger {
|
|
||||||
case OrganizeTriggerScheduled:
|
|
||||||
return "自动整理重命名刮削入库"
|
|
||||||
case OrganizeTriggerDownload:
|
|
||||||
return "下载完成自动整理重命名刮削入库"
|
|
||||||
default:
|
|
||||||
if req.DryRun {
|
|
||||||
return "预览整理重命名入库"
|
|
||||||
}
|
|
||||||
return "手动整理重命名刮削入库"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) failureMessage(req OrganizePipelineRequest) string {
|
|
||||||
switch req.Trigger {
|
|
||||||
case OrganizeTriggerScheduled:
|
|
||||||
return "自动整理重命名入库失败"
|
|
||||||
case OrganizeTriggerDownload:
|
|
||||||
return "下载完成自动整理失败"
|
|
||||||
default:
|
|
||||||
return "手动整理重命名入库失败"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) completedMessage(req OrganizePipelineRequest) string {
|
|
||||||
switch req.Trigger {
|
|
||||||
case OrganizeTriggerScheduled:
|
|
||||||
return "自动整理重命名刮削入库结束"
|
|
||||||
case OrganizeTriggerDownload:
|
|
||||||
return "下载完成自动整理入库结束"
|
|
||||||
default:
|
|
||||||
return "手动整理重命名刮削入库结束"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) defaultSourcePath(ctx context.Context, req OrganizePipelineRequest) string {
|
|
||||||
if p == nil || p.organizer == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if req.Scope == OrganizeScopeDirectory {
|
|
||||||
return p.organizer.defaultSourceRoot(ctx, "")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *OrganizePipelineService) defaultDestPath(ctx context.Context, req OrganizePipelineRequest) string {
|
|
||||||
if p == nil || p.organizer == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if req.Scope == OrganizeScopeDirectory {
|
|
||||||
return p.organizer.defaultDestRoot(ctx, "")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func organizeScanRoot(res *OrganizeResult, path string) string {
|
||||||
|
if res == nil {
|
||||||
|
if strings.TrimSpace(path) == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return filepath.Dir(path)
|
||||||
|
}
|
||||||
|
var root string
|
||||||
|
for _, item := range res.Items {
|
||||||
|
if !organizeItemNeedsVisibilitySync(item) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
target := strings.TrimSpace(item.Target)
|
||||||
|
if target == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dir := filepath.Dir(target)
|
||||||
|
if root == "" {
|
||||||
|
root = dir
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
root = commonPathRoot(root, dir)
|
||||||
|
}
|
||||||
|
if root != "" {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(path) != "" {
|
||||||
|
return filepath.Dir(path)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(res.DestPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func organizeItemNeedsVisibilitySync(item OrganizePreviewItem) bool {
|
||||||
|
switch item.Action {
|
||||||
|
case "organize", "replace", "reclassify", "cleanup":
|
||||||
|
return true
|
||||||
|
case "skip":
|
||||||
|
switch item.Reason {
|
||||||
|
case organizeSkipAlreadyOrganized, organizeSkipTargetExists, "duplicate exists", "target exists":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonPathRoot(a, b string) string {
|
||||||
|
a = filepath.Clean(strings.TrimSpace(a))
|
||||||
|
b = filepath.Clean(strings.TrimSpace(b))
|
||||||
|
if a == "" || a == "." {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
if b == "" || b == "." {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
if pathWithin(a, b) {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
if pathWithin(b, a) {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
parent := filepath.Dir(a)
|
||||||
|
if parent == a || parent == "." {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
if pathWithin(b, parent) {
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
a = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) startTask(ctx context.Context, req OrganizePipelineRequest, opts OrganizeOptions) *TaskHandle {
|
||||||
|
if p == nil || p.tasks == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name := strings.TrimSpace(req.TaskName)
|
||||||
|
if name == "" {
|
||||||
|
name = p.defaultTaskName(req)
|
||||||
|
}
|
||||||
|
message := "正在整理/重命名/入库"
|
||||||
|
if req.DryRun {
|
||||||
|
message = "正在预览整理/重命名"
|
||||||
|
}
|
||||||
|
return p.tasks.Start(TaskKindOrganize, name, TaskUpdate{
|
||||||
|
Stage: "organize",
|
||||||
|
SourcePath: firstNonEmpty(opts.SourcePath, p.defaultSourcePath(ctx, req)),
|
||||||
|
DestPath: firstNonEmpty(opts.DestPath, p.defaultDestPath(ctx, req)),
|
||||||
|
Message: message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) finishTask(task *TaskHandle, err error, stage, message string, res *OrganizeResult) {
|
||||||
|
if task == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
task.Finish(err, TaskUpdate{
|
||||||
|
Stage: stage,
|
||||||
|
Message: message,
|
||||||
|
Metrics: OrganizeTaskMetrics(res),
|
||||||
|
Details: OrganizeTaskDetails(res, 8),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) defaultTaskName(req OrganizePipelineRequest) string {
|
||||||
|
switch req.Trigger {
|
||||||
|
case OrganizeTriggerScheduled:
|
||||||
|
return "自动整理重命名刮削入库"
|
||||||
|
case OrganizeTriggerDownload:
|
||||||
|
return "下载完成自动整理重命名刮削入库"
|
||||||
|
default:
|
||||||
|
if req.DryRun {
|
||||||
|
return "预览整理重命名入库"
|
||||||
|
}
|
||||||
|
return "手动整理重命名刮削入库"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) failureMessage(req OrganizePipelineRequest) string {
|
||||||
|
switch req.Trigger {
|
||||||
|
case OrganizeTriggerScheduled:
|
||||||
|
return "自动整理重命名入库失败"
|
||||||
|
case OrganizeTriggerDownload:
|
||||||
|
return "下载完成自动整理失败"
|
||||||
|
default:
|
||||||
|
return "手动整理重命名入库失败"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) completedMessage(req OrganizePipelineRequest) string {
|
||||||
|
switch req.Trigger {
|
||||||
|
case OrganizeTriggerScheduled:
|
||||||
|
return "自动整理重命名刮削入库结束"
|
||||||
|
case OrganizeTriggerDownload:
|
||||||
|
return "下载完成自动整理入库结束"
|
||||||
|
default:
|
||||||
|
return "手动整理重命名刮削入库结束"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) defaultSourcePath(ctx context.Context, req OrganizePipelineRequest) string {
|
||||||
|
if p == nil || p.organizer == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if req.Scope == OrganizeScopeDirectory {
|
||||||
|
return p.organizer.defaultSourceRoot(ctx, "")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *OrganizePipelineService) defaultDestPath(ctx context.Context, req OrganizePipelineRequest) string {
|
||||||
|
if p == nil || p.organizer == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if req.Scope == OrganizeScopeDirectory {
|
||||||
|
return p.organizer.defaultDestRoot(ctx, "")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user